1. 自己写的socket的shutdown和close相关测试
编号 | 测试手段 | 测试结果 | 附加测试 | 附加测试结果 | |
1 | shutdown(fd, 0)【不能再读】 | write | 成功,shutdown之后netstat显示C和S的状态均为established(没有发送FIN). | close后再write | close后netstat显示server的socket为FIN_WAIT_2,write执行后返回-1,errno=9[EBADF] |
recv | 返回0,netstat同上 | ||||
2 | shutdown(fd,1)【不能再写】 | write | 执行该语句时,server向client发送了FIN,所以netstat显示server为FIN_WAIT_2,缓冲区为空;client为CLOSE_WAIT,接收缓冲区有1B。 执行write时受到信号SIGPIPE,服务器端程序退出。 客户端一直处于CLOSE_WAIT状态 | ||
recv | 执行该语句时,server向client发送了FIN,所以netstat显示server为FIN_WAIT_2,缓冲区为空;client为CLOSE_WAIT,接收缓冲区有1B。 过了5分钟server一直处于FIN_WAIT_2状态,recv一直阻塞【如果有数据来,在接收缓冲区,那么recv成功】 | ||||
3 | shutdown(fd, SHUT_RDWR)【不能读写】 | write | 收到SIGPIPE信号,程序退出,netstat显示server处于FIN_WAIT_2状态,2个buffer为空,通过tcpdump抓包可以看到server向client发送了一个FIN,并且client回复了ACK;而client端为CLOSE_WAIT状态,接收缓存区有1B,发送缓冲区为空。因为一直在pause()等待信号的到来 | ||
recv | 返回0,netstat同上 | ||||
4 | shutdown(fd, 0)+close | write | close发送reset过去,server和client的socket均变为closed状态。 Write返回-1,errno=9 | ||
recv | 同上 | ||||
5 | shutdown(fd,1)+close | write | 返回-1,errno=9; 执行shutdown时,发送FIN,执行close时发送RST.netstat显示两端均为closed状态。再执行write/recv必然errno=9 | ||
recv | 同上 | ||||
6 | shutdown(fd, SHUT_RDWR)+close | write | 同上 | ||
recv | 同上 | ||||
7 | 多次相同的shutdown(fd, n) | 只有第一次的有效,后面的无效 | |||
8 | shutdown(fd,0) | shutdown(fd,1) | 第一次shutdown没有发送FIN,第二次发送FIN,到状态FIN_WAIT_2. | ||
shutdown(fd,2) | |||||
9 | close | write | close发送reset过去,server和client的socket均变为closed状态。 本进程的Write返回-1,errno=9 其他进程可以继续write/recv,参见bwserver中fork那段程序 | ||
recv | 同上 |
2.文字补充说明:
close | 使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。 |
如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放 | |
shutdown | shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接 |
在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程. |