下边是客户端代码:
1 #include <mylib.h> 2 int main(void) 3 { 4 int sock_fd; 5 sock_fd=socket(AF_INET,SOCK_STREAM,0); 6 7 struct sockaddr_in serv_add; 8 bzero(&serv_add,sizeof(serv_add)); 9 serv_add.sin_family=AF_INET; 10 serv_add.sin_port=htons(SERV_PORT); 11 struct in_addr add; 12 inet_aton("192.168.1.105",&add); 13 serv_add.sin_addr=add; 14 15 if(connect(sock_fd,(struct sockaddr *)&serv_add,sizeof(serv_add))<0) 16 sys_err("connect error!\n"); 17 char sendbuff[MAXLINE],recvbuff[MAXLINE]; 18 char *temp; 19 ssize_t n; 20 while ((temp=fgets(sendbuff,sizeof(sendbuff),stdin)) !=NULL) 21 { 22 int k; 23 if((k=write(sock_fd,sendbuff,sizeof(sendbuff)))<0) 24 { 25 26 } 27 if((n=read(sock_fd,recvbuff,sizeof(recvbuff)))>0) 28 printf("SVR:%s",recvbuff); 29 if(n<0) 30 printf("fail to get data from server %s\n",inet_ntoa(serv_add.sin_addr)); 31 if(n==0) 32 { 33 //broken pipe ,haha sigpipe 34 printf("%s","server defunct\nclosing the socket..."); 35 close(sock_fd); 36 } 37 } 38 return 0; 39 } |
解释一下客户端代码:
第5行:sock_fd=socket(AF_INET,SOCK_STREAM,0); 用socket函数创建一个sock,第一个参数是协议族,我们用AF_INET代表tcp/ip协议族。第二个参数代表流方式,也就是TCP 字节流方式。第三个参数,额...貌似有点高深,说实话,不懂,注释说 If it is zero, is chosen automatically. 就是自动选择,我擦,这一自动,我感觉整个人都不舒服了...
行7:struct sockaddr_in serv_add; 定义一个sock 地址结构,用来存放服务器断ip,端口,协议族之类的。
行10,12:这两行里都有一个来处理端口和ip,为啥,这里牵扯一个“字节序”的问题,处理器对字节的排列顺序不是相同的,这个可以百度以下,呵呵
行15:用本地初始化的sock和服务端地质结构建立连接。等等,为啥客户端sock没有地址和端口呢,怎么直接就连接了,这不科学。额,就这在这一不,tcp默认将本地sock地址设为本地ip,端口在允许范围内随机取值,一般不会是vip端口(<1024)啦。而且每次链接都会随机端口。好,地址设好就可以连接服务器了,进行关键的三次握手。
行20,23:从输入设备读取 输入值。写入打开的 socket 文件符。将输入值 写入建好的 pipe里。这里的write为什么回有小于0的情况呢,原因是,当服务起进程断开连接,或者不小心关闭时,服务端乎发给客户端一个FIN,表示终止链接,但是由于TCP是半关闭的,客户端可能正在输入,不知道服务端已经断开了,服务端TCP会返回一个RST,告诉客户端管道不通。这时如果继续将值写入pipe,系统就会立马提示你 管道断裂,发一个SIGPIPE信号给你。这个信号很要命啊,你不捕获处理,系统就默认关掉你的进程。处理了,write就返回小于0
行27:读取服务器的返回值,读取失败就返回小于0
行31:同样,服务断断开后,客户端已收到FIN的通知,read后直接返回0. 这里为了不让出现23行的问题,干脆把socket关闭了
下边是服务端代码:
1 #include <mylib.h> 2 3 int main(void) 4 { 5 int listen_fd , connected_fd; 6 struct sockaddr_in serv_add; 7 //----------------------------------------------------------------------------- 8 listen_fd=socket(AF_INET,SOCK_STREAM,0); 9 serv_add.sin_family=AF_INET; 10 serv_add.sin_port=htons(SERV_PORT); 11 serv_add.sin_addr.s_addr=htonl(INADDR_ANY); 12 //------------------------------------------------------------------------------ 13 if(bind(listen_fd,(struct sockaddr *)&serv_add,sizeof(serv_add))<0) 14 sys_err("bind error\n"); 15 if(listen(listen_fd,LISTENQ)<0) 16 sys_err("listen error\n"); 17 18 signal(SIGCHLD,sig_chld); 19 20 __pid_t pid; 21 while (1) { 22 connected_fd = accept(listen_fd,0,0); 23 if(connected_fd<0){ 24 if(errno==EINTR) 25 { 26 printf("interrupt\n"); 27 continue; 28 } 29 else 30 sys_err("accept eero!\n"); 31 } 32 if((pid=fork())==0) 33 { 34 char recevBuff[MAXLINE]; 35 int n; 36 close(listen_fd); 37 while ((n=read(connected_fd,recevBuff,MAXLINE))>0) { 38 printf("Client:%s",recevBuff); 39 write(connected_fd,recevBuff,MAXLINE); 40 } 41 if(n<0) 42 sys_err("read error\n"); 43 close(connected_fd); 44 exit(0); 45 } 46 close(connected_fd); 47 } 48 return 0; 49 } |