本文共 4343 字,大约阅读时间需要 14 分钟。
在四次挥手中, 被动关闭的一端进入CLOSE_WAIT状态, 此时, 如果还在这个socket上发送数据, 那么主动关闭(这是说的是close关闭, 而非shundown关闭, 他们有区别, 我们后面再说)的一端会返回RST.
我们来看看:
服务端程序为:
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(){ int sockSrv = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_family = AF_INET; addrSrv.sin_addr.s_addr = INADDR_ANY; addrSrv.sin_port = htons(8765); bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); listen(sockSrv, 5); struct sockaddr_in addrClient; int len = sizeof(struct sockaddr_in); int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, (socklen_t*)&len); while(1) { char szRecvBuf[50001] = {0}; int iRet = recv(sockConn, szRecvBuf, sizeof(szRecvBuf) - 1, 0); printf("iRet is %d\n", iRet); getchar(); close(sockConn); } while(1); close(sockSrv); return 0;}
先启动它。
客户端程序为:
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(){ int sockClient = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8765); connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); while(1) { #define N 200 char szSendBuf[N] = {0}; for(unsigned int i = 0; i < N; i++) //字符数组最后一个字符不要求是‘\0’ { szSendBuf[i] = 'a'; } int iRet = send(sockClient, szSendBuf, sizeof(szSendBuf) , 0); printf("send size is %d, iRet is %d\n", sizeof(szSendBuf), iRet); getchar(); } close(sockClient); return 0;}
再启动它。
三次握手建立后, 客户端给服务端正常发送数据。 服务端接受到数据后, 调用close来主动关闭链接, 此时客户端进入CLOSE_WAIT状态, 如果客户端继续在这个socket上发送数据, 那么服务端给回RST包, 看看结果:
xxxxxx$ ./serveriRet is 200 第一次收200字节iRet is -1 socket已经关闭,所以本次recv返回-1
xxxxxx$ netstat -nao | grep 8765tcp 0 0 10.100.70.139:41849 10.100.70.140:8765 ESTABLISHED off (0.00/0/0) 三次握手后的状态xxxxxx$ xxxxxx$ xxxxxx$ xxxxxx$ netstat -nao | grep 8765tcp 1 0 10.100.70.139:41849 10.100.70.140:8765 CLOSE_WAIT off (0.00/0/0) 服务端主动关链接后客户端socket的状态
xxxxxx$ ./clientsend size is 200, iRet is 200 第一次发送200字节send size is 200, iRet is 200 变成CLOSE_WAIT后, 继续发送200字节
21:21:52.595187 IP 10.100.70.139.41849 > 10.100.70.140.ultraseek-http: Flags [P.], seq 201:401, ack 2, win 56, options [nop,nop,TS val 1559812393 ecr 1559808982], length 200 0x0000: 4500 00fc 80ef 4000 4006 172e 0a64 468b E.....@.@....dF. 0x0010: 0a64 468c a379 223d aede 4129 a44f 9d3c .dF..y"=..A).O.< 0x0020: 8018 0038 a2cd 0000 0101 080a 5cf8 d929 ...8........\..) 0x0030: 5cf8 cbd6 6161 6161 6161 6161 6161 6161 \...aaaaaaaaaaaa 0x0040: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x0050: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x0060: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x0070: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x0080: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x0090: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa 0x00f0: 6161 6161 6161 6161 6161 6161 0000 0000 aaaaaaaaaaaa.... 0x0100: 0000 0000 0000 0000 0000 0000 ............21:21:52.595378 IP 10.100.70.140.ultraseek-http > 10.100.70.139.41849: Flags [R], seq 2756681020, win 0, length 0 0x0000: 4500 0028 a2a2 4000 4006 f64e 0a64 468c E..(..@.@..N.dF. 0x0010: 0a64 468b 223d a379 a44f 9d3c 0000 0000 .dF."=.y.O.<.... 0x0020: 5004 0000 06bf 0000 0000 0000 0000 0000 P............... 0x0030: 0000 0000 0000 0000 ........我们见到RST了, 很容易理解, 服务端都已经发出FIN表示请求关闭了, 你客户端还发数据过去, 有意义么? 直接给你RST
转载地址:http://rjwti.baihongyu.com/