当前位置: 首页 > Linux

调用close()后发生了什么

时间:2023-04-07 03:14:20 Linux

场景介绍我们考虑一个简单的客户端-服务器通信场景,其典型模式是:服务器通过close()主动关闭一个TCP连接。客户端通过read()获取到0(表示服务端没有数据),调用close()关闭连接。在TCP层面,表现为:服务端调用close()后,发送一个FIN给客户端,客户端回应一个FIN-ACK。服务器进入FIN-WAIT-2状态,客户端进入CLOSE-WAIT状态。客户端调用close()后,向服务器发送FIN,服务器会使用FIN-ACK。服务器进入TIME-WAIT状态,客户端直接进入CLOSE状态,连接结束。我们考虑一些异常情况,在客户端:客户端获取到read()==0后没有及时调用close();客户端获取到read()==0后仍然向服务端写入数据。测试程序使用《UNIX网络编程》(第一卷)中的server-client示例程序。服务器部分:intmain(intargc,char**argv){intlistenfd,connfd;socklen_tlen;structsockaddr_inservaddr,cliaddr;字符buff[MAXLINE];time_t滴答作响;listenfd=Socket(AF_INET,SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_addr.s_addr=htonl(INADDR_ANY);servaddr.sin_port=htons(9999);/*白天服务器*/Bind(listenfd,(SA*)&servaddr,sizeof(servaddr));听(listenfd,LISTENQ);对于(;;){len=sizeof(cliaddr);connfd=Accept(listenfd,(SA*)&cliaddr,&len);printf("connectionfrom%s,port%d\n",Inet_ntop(AF_INET,&cliaddr.sin_addr,buff,sizeof(buff)),ntohs(cliaddr.sin_port));滴答声=t时间(空);snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks));写(connfd,buff,strlen(buff));关闭(connfd);}}server监听9999端口,建立新连接后,发送当前时间,然后调用close()关闭连接客户端部分:intmain(intargc,char**argv){intsockfd,n;socklen_tlen;字符recvline[MAXLINE+1];structsockaddr_inservaddr,cliaddr;if(argc!=2)err_quit("usage:a.out");if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)err_sys("套接字错误");bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(9999);/*白天服务器*/if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0)err_quit("inet_ptonerrorfor%s",argv[1]);if(connect(sockfd,(SA*)&servaddr,sizeof(servaddr))<0)err_sys("连接错误");len=sizeof(cliaddr);Getsockname(sockfd,(SA*)&cliaddr,&len);printf("本地地址:%s\n",Sock_ntop((SA*)&cliaddr,sizeof(cliaddr)));while((n=read(sockfd,recvline,MAXLINE))>0){recvline[n]=0;/*空终止*/if(fputs(recvline,stdout)==EOF)err_sys("fputserror");}if(n<0)err_sys("读取错误");退出(0);}客户端没有及时调用close()调用我们修改客户端调用close()的处理流程当read()==0时,阻塞休眠。等待一段时间后,发送SIGINT让进程退出,相当于调用close()。注意到如下现象:服务器SOCKET在FIN-WAIT-2状态时,发送SIGINT信号让客户端退出,客户端发送FIN,服务器回复FIN-ACK。此时,按照正常流程结束链接。服务器SOCKET等待FIN-WAIT-2状态超时后,客户端发送FIN,服务器回复RST结束链接。OrphanSocket:从应用的角度来看,这个socket连接已经完成发送和接收数据,关闭连接,但是为了在linux内核中完成正常的tcp协议(比如缓冲区中的数据)转换,它会在内核的tcp协议层继续维护这些sock状态,直到系统回收。处于此状态的套接字是孤立套接字。分析:服务器SOCKET关闭后,没有引用这个SOCKET。这个SOCKET进入“orphanSOCKET”状态。当孤儿Socket存在时,由系统协议栈负责完成后续的FIN流程。当孤儿Socket超时后,系统协议栈中就没有这个Socket的信息了。客户端此时发送FIN,会收到一个RST响应。

最新推荐
猜你喜欢