#include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> bool server(char *ip,int port){ int socketfd = 0; if(-1 ==(socketfd = socket(AF_INET,SOCK_STREAM,0))){ printf("create socket faile,errno:%d\n",errno); return false; } sockaddr_in serverAddr; memset(&serverAddr,0,sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = inet_addr(ip); if(-1==bind(socketfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr))){ printf("bind socket fail,errno:%d\n",errno); return false; } if(-1==listen(socketfd,10)){ printf("listen socket fail,errno:%d\n",errno); return false; } printf("server has started...\n"); int confd = 0; sockaddr_in clientAddr; memset(&clientAddr,0,sizeof(clientAddr)); int sockLen = 0; if(-1==(confd = accept(socketfd,(struct sockaddr *)&clientAddr,(socklen_t*)&sockLen))){ printf("accept socket fail,errno:%d\n",errno); return false; } int len = 0; while(1){ char recvBuf[64]={0}; len = recv(confd,recvBuf,sizeof(recvBuf),0); printf("len:%d,str:%s\n",len,recvBuf); if(len ==0){ printf("client shutdown socket...\n"); break; } } while(1){ sleep(3); } return true; } bool client(char *ip,int port){ int socketfd = 0; if(-1 == (socketfd = socket(AF_INET,SOCK_STREAM,0))){ printf("create socket fail,errno:%d\n",errno); return false; } sockaddr_in serverAddr; memset(&serverAddr,0,sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = inet_addr(ip); if(-1==connect(socketfd,(struct sockaddr*)&serverAddr,sizeof(serverAddr))){ printf("connect socket fail,errno:%d\n",errno); return false; } char * sendBuf = "hello world"; send(socketfd,sendBuf,strlen(sendBuf)+1,0); while(1){ sleep(3); } return true; } int main(int argc, char *argv[]) { if(argc!=4){ printf("usage:CloseWaitTest [0|1] ip port. 0:server,1:client\n"); return 1; } if(atoi(argv[1])==0){ server(argv[2],atoi(argv[3])); } if(atoi(argv[1])==1){ client(argv[2],atoi(argv[3])); } return 0; }
测试1:进程退出的方式关闭连接。正常关闭客户端进程,服务端会收到来自于客户端的关闭请求,服务器端的连接套接字状态进入CLOSE_WAIT,由于服务器端没有主动发送关闭请求,所以客户端的套接字状态处于FIN_WAIT2
正常运行截图
服务器端的监听套接字处于LISTEN状态,服务器和客户端直接的连接套接字处于ESTABLISHED状态
ctrl+c将客户端退出
服务器端套接字处于CLOSE_WAIT状态,客户端进程套接字处于FIN_WAIT2状态,FIN_WAIT2超时后系统会回收该套接字资源,超时时间系统默认为60秒,可以通过通过 /sbin/sysctl -a | grep fin_timeout查看
由于服务器端一直没有主动关闭所以一直处于CLOSE_WAIT状态
测试2: