关于send侦测socket是否有效
当socket用WSAAsyncSelect设置非阻塞模式后,由于网络等原因,会使FD_CLOSE事件触发不了(原先总是在本机调试,不会出现FD_CLOSE事件触发不了这种情况,我没遇到过)。所以就有心跳包进行检测。 经测试,在用send向socket发送数据时,如果socket已无效,send不会返回错误,但这时就会触发FD_CLOSE事件。
socket发送失败(send)
自:http://blog.sina.cn/dpool/blog/s/blog_6648c11401011j1z.html
当时做JRU网络通信时,就是通过判断send函数的返回值来判断服务器与客户端之间的网络连接是否正常,但是send成功时,并不意味着对方的recv函数就一定可以收到数据。
send发送成功只是说明send函数成功的把用户的数据写入到了网口芯片的发送缓存中,但是并不代表缓存中的数据已经发送成功,并且成功收到对方的确认ACK(计算机网络的相关知识)。
对于阻塞的send来说,即使网口的缓存中的空间已满,它依然不会返回错误,而会一直等待着有空余的缓存出现知道能把send中所有的数据都放进去为止。
send何时会发生错误呢?
我在网上没有找到自己想要的资料,都是说当其中网络连接出错时,在下一次send时就会返回错误。我结合我学过的计算机网络的知识说一下自己的想法,如果不准确,请多多指导下。
tcp协议send发送成功后是要求返回确认帧的(并不是每个都返回,可以在收到多个数据之后返回)。在网络中传输的数据帧是有一定的生存时间的,在IP协议中,就写了ip数据包的生存时间,也就是说,数据在网络中的传输是有时间限制的,如果socket通信的两端之间存在大量的路由器,或者网络突然出现了问题,没有从一段到另一端的路由,也许在规定的时间内数据无法正确的到达接收端,这样接收端也就无法返回一个ACK确认帧。如果发送端在一定时间内没有收到ACK确认帧,驱动程序就会告诉上层的在此调用的send函数,发送失败。
我自己也做了一下实验,当用我们自己的monitor与server相连,monitor连接了我自己写的一个数据发送程序(发数比较慢,所以不会在很短的时间内填满缓冲区),同时电脑上还挂着飞信和QQ。我电脑的网线连接到交换机A上,交换机通过一根网线连接到主交换机B上,当我断开交换机A与B之间的连接时(因为如果直接拔网线的话,电脑可以自动确定无网络连接)这三个程序都没有立即断开,都是过了一段时间才断开的,其中monitor是最先显示无法连接服务器的,因为它不断发送数据调用send函数能及时发现网络不通(网络返回错误信息后的再次调用send才会知道发送已经出现问题)的缘故。飞信与QQ都是过了一段时间才先后断开,我猜测是因为这两个软件每隔一段时间就给服务器发一条信息,以告诉服务器,自己还活着,因为他们send函数之间 的时间间隔比我们monitor的send之间的时间间隔要长很多,所以才会晚断开一会。