先直接上正确答案:soket的close方法可以释放一个连接的资源,但是不是立即释放,如果想立即释放,那么请在close之前使用shutdown方法。
shutdown 方法是用来实现通信模式的,模式分三种,SHUT_RD 关闭接收消息通道,SHUT_WR 关闭发送消息通道,SHUT_RDWR 两个通道都关闭
#关闭接收通道
tcp_soket.shutdown(0)
#关闭发送通道
tcp_soket.shutdown(1)
#两个通道都关闭
tcp_soket.shutdown(2)
我们仅仅用close关闭tcp连接是不可行的,应该在调用close前先使用shutdown关闭接收或者是发送通道,如何仅仅只用了发送功能传参填写1接收也是这样,如果两者都用了就向传参输入2
今天发现写的tcp发包工具在测试过程中,使用Wireshark抓包发现,在发包结束后 发送端并没有发出挥手包
一开始以为是遗漏了close, 后来发现源代码里面确实有close
排查了一圈问题后在网上发现,soket的close方法可以释放一个连接的资源,但是不是立即释放,如果想立即释放,那么得在close之前使用shutdown方法
shutdown方法是用来实现通信模式的,模式分三种,SHUT_RD 关闭接收消息通道,SHUT_WR 关闭发送消息通道,SHUT_RDWR 两个通道都关闭
也就是说,想要关闭一个连接,首先把通道全部关闭,然后在release连接,以上三个静态变量分别对应数字常量:0,1,2
根据 shutdown说明文档,尝试在close前面假 shutdown(2)既关闭发送接收通道
关闭发送和接收通道发现确实有挥手包了
tcp_soket.shutdown(2)
tcp_soket.close()
但是发包后抓包发现依旧没有挥手包
很奇怪我仔细观察了其他教程的写法,发现他们都用shutdown这个方法解决了这个问题,经过我的验证发现我只调用了send没有调用recv所以是不是我应该只需要释放发送通道,于是我尝试将shutdown的传参改为 1
tcp_soket.shutdown(1)
tcp_soket.close()
抓包发现确实有变化但是好像跟我想象中的不一样可以看得出来下面这个图片只有我这边发的一个fin报文好像后面就直接断开了
于是我就尝试在两条函数之间加了一个input看看这个fin报文在那个环节发出来的
加了input后发现挥手包直接发出来了也完成了断开链接
于是我就尝试在中间加一个sleep完美解决该问题
初步判断是程序执行的太快了还没来得及挥手就close掉了所以家里sleep可以解决该问题