day6-socket编程C/S模型
来源:互联网 发布:淘宝写手兼职招聘 编辑:程序博客网 时间:2024/06/06 03:29
C/S模型-TCP
下图是基于TCP协议的客户端/服务器程序的一般流程:
server.c
socket() 建立套接字
bind() 绑定IP 端口号 (struct sockaddr_in addr 初始化)
listen() 指定最大同时发起连接数
accept() 阻塞等待客户端发起连接
read()
小–大
write 给 客户端
close();
client.c
socket();
bind(); 可以依赖“隐式绑定”
connect();发起连接
write();
read();
close();
服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。
数据传输的过程:
建立连接后,TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()返回后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。
如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数据。
在学习socket API时要注意应用程序和TCP协议层是如何交互的: 应用程序调用某个socket函数时TCP协议层完成什么动作,比如调用connect()会发出SYN段 应用程序如何知道TCP协议层的状态变化,比如从某个阻塞的socket函数返回就表明TCP协议收到了某些段,再比如read()返回0就表明收到了FIN段
server
下面通过最简单的客户端/服务器程序的实例来学习socket API。
注意:本程序没有加入错误处理,后面会封装好加上
server.c的作用是从客户端读字符,然后将每个字符转换为大写并回送给客户端。
/************************************************************************* > File Name: serverad.c > Author: sunxingying > Mail: 1159015605@qq.com > Created Time: 2017年02月25日 星期四 05时31分20秒 ************************************************************************/#include<stdio.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<strings.h>#include<sys/socket.h>#include<netinet/in.h>#define SERV_PORT 6666int main(){ int sfd,cfd; int len,i; char buf[1024],clie_IP[1024]; struct sockaddr_in serv_addr,clie_addr; socklen_t clie_addr_len; /*创建一个socket指定IPV4协议族 TCP协议*/ sfd=socket(AF_INET,SOCK_STREAM,0); /*初始化一个地址结构 man 7 ip查看对应信息*/ //将整个结构体清零 bzero(&serv_addr,sizeof(serv_addr)); //选择协议族为IPV4 serv_addr.sin_family=AF_INET; //监听本地所有IP地址 serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); //绑定端口号 serv_addr.sin_port=htons(SERV_PORT); //绑定服务器地址结构 bind(sfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); //设定链接上限,注意此处不阻塞,同一时刻允许向服务器发起链接请求的数量 listen(sfd,64); printf("wait for client connect....\n"); //获取客户端地址结构大小 clie_addr_len=sizeof(clie_addr_len); //参数1是sfd;参数2传出参数,参数3传入传出参数,全部是client端的参数 //成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno //监听客户端链接会阻塞 cfd=accept(sfd,(struct sockaddr *)&clie_addr,&clie_addr_len); printf("主机IP:%s\n 主机端口号%d\n",inet_ntop(AF_INET,&clie_addr.sin_addr.s_addr,clie_IP,sizeof(clie_IP)),ntohs(clie_addr.sin_port)); while(1) { //读取客户端发送数据 len=read(cfd,buf,sizeof(buf)); write(STDOUT_FILENO,buf,len); //处理客户端数据 for(i=0;i<len;i++) { buf[i]=toupper(buf[i]); } //处理完数据回写给客户端 write(cfd,buf,len); } //记得要关闭文件 close(sfd); close(cfd); return 0;}
client
client.c的作用是从命令行参数中获得一个字符串发给服务器,然后接收服务器返回的字符串并打印。
/************************************************************************* > File Name: client.c > Author: sunxingying > Mail: 1159015605@qq.com > Created Time: 2017年05月24日 星期三 05时43分20秒 ************************************************************************/#include<string.h>#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/socket.h>#include<arpa/inet.h>#define SERV_IP "127.0.0.1"#define SERV_PORT 6666int main(void){ int cfd; char buf[1024]; struct sockaddr_in serv_addr; socklen_t serv_addr_len; cfd=socket(AF_INET,SOCK_STREAM,0); int n; memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(SERV_PORT); inet_pton(AF_INET,SERV_IP,&serv_addr.sin_addr.s_addr); connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); while(1) { fgets(buf,sizeof(buf),stdin); write(cfd,buf,strlen(buf)); n=read(cfd,buf,sizeof(buf)); write(STDOUT_FILENO,buf,n); } close(cfd); return 0;}
运行结果如下:
socket模型
- day6-socket编程C/S模型
- day6-socket编程-函数
- Tcp C/S socket编程
- C语言socket编程模型
- C-socket编程-Select()模型
- 最简单的socket c/s模型
- Socket创建C/S模型的小结
- java C/S socket 网络通讯模型
- Linux Socket通信 C/S模型
- socket编程--TCP客户/服务器模型 (c/s)及基本函数
- socket编程 -- 基于TCP协议的C/S通信模型及实现
- socket编程 -- 基于UDP协议的C/S通信模型及实现
- (四十九)socket编程——网络套接字函数及建立C/S模型(TCP)
- Android/Socket编程 简单C/S模式
- C-socket编程-客户端服务端通信模型
- (五十)socket编程——出错函数的封装和基于UDP的C/S模型
- Socket的C/S模型与TCP关系
- socket之回射c/s模型(一)
- 自定义View-轻量级柱状图、饼图、折线图
- QtXlsxWriter---Qt操作excel文件
- 提取回文数
- cout问题
- mac 在php工程中实现curl的https访问
- day6-socket编程C/S模型
- 小程序----路由(2)
- Altium Designer中测量Gerber文件两个点之间的距离
- 子父类构造代码块/静态代码块/普通代码块执行顺序....(涉及父类静态中再次创建子类对象的特殊情况)
- MongoDB C100DEV 0.综述
- 《软技能--代码之外的生存指南》————第七篇---精神
- BZOJ2763: [JLOI2011]飞行路线
- SimpleDateFormat使用详解
- LeetCode 448. Find All Numbers Disappeared in an Array