WSAGetLastError可能会返回10053错误,查msdn的解释是:
WSAECONNABORTED 10053
神马?软件原因造成的连接中断,这是什么意思,不跟没说一样的么? Berkeley description: A connection abort was caused internal to your host machine. The software caused a connection abort because there is no space on the socket’s queue and the socket cannot receive further connections.
WinSock description: Partly the same as Berkeley. The error can occur when the local network system aborts a connection. This would occur if WinSock aborts an established connection after data retransmission fails (receiver never acknowledges data sent on a datastream socket).
TCP/IP scenario: A connection will timeout if the local system doesn’t receive an (ACK)nowledgement for data sent. It would also timeout if a (FIN)ish TCP packet is not ACK’d (and even if the FIN is ACK’d, it will eventually timeout if a FIN is not returned).
伯克利说这种连接中断是因为宿主机器的内部原因,因为软件导致的连接中断,可能是因为socket的队列满并且这个socket不能接收更多的连接了。 The Scenario: Meanwhile, the client is still happily writing the remainder of the HTTP request to the socket. (Remember a TCP/IP socket connection needs to be closed from both sides. In this case, the server has closed its side, but the client is still pumping data into the half-open connection.) Go back and re-read the original error explanations. Hopefully, after that explanation, you’ll say "Aha! I understand what they’re talking about!".
啊哈,又有http了,大概意思就是http server收到请求了,但发现有问题,那么回一个http错误码,然后就关闭了socket,但与此同时,client端还在很开心地向socket写数据,注意哦,tcp是全双工的。client写完毕后,实际上数据只是放到了发送方的缓冲区中,不一定已经发出去了,如果写得不好的程序,这个时候就开始从socket读数据了,这时候就会产生一个WSACONNECTABORTED错误,windows上对应的就是10053错误。 但这个解释实际上是不能让人满意的,只是举出了一种场景,但为什么会产生还没有解释。后面又搜到了个参考2,首先解释10053错误是收到fin后client会放弃发送缓冲区中的数据,同时上报错误。虽然说法还有点一头雾水。 不过这两个参考给我们一个思路,重现这个问题。 于是简单写个测试用的c-s程序,大概流程如下
图1 CS程序简化流程图 这个简单程序演示如何出现10053错误(以及10054错误)。 如果server在收到client发送的数据后立即关闭socket,那么client再读时,会收到10053错误;如果server收到发送数据后,立即crash,那么随后client再读取时会收到10054错误。 ok,能够重现场景了,那么我们来分析一下更细节的方面,网络问题自然是抓包,本问题处理抓包还要看一下tcp的状态以便辅助分析,我们在client端每次操作之前都打印当前的tcp状态。 下面是client端发送记录和对应的netstat情况 图2 10053错误client端tcp状态流转 client在发送之前tcp状态是established,在发送之后,server会立即关闭,tcp状态也变为close_wait,但这只是单方向的关闭,client可以继续发数据,但client发送后,server立即退出了,导致后续recv会失败并且返回10053。对应抓包情况如下:
图3 10053错误client端tcp抓包 整个通信过程如下:
图4 10054错误client端tcp状态流转 可以看到在crash之前这个tcp都是established状态。crash之后,client端接收数据时会收到10054错误,场景重现了,我们再看一下抓包情况
图5 10054错误client端tcp抓包 这个抓包情况跟10053很像,1-7也同10053,在8时,client收到server发过来的reset,表示当前连接被强制复位了。 7.回过头来在看一开始的解释,所谓软件原因造成的连接终端,就是本例子中,server端在shoutdown本方向传输时,立即关闭了socket,导致本应该等待对方发送fin来完全结束的正常逻辑被打破,编程单方向强制中止本次tcp,导致client端之后向上报错,就是所谓的10053错误了,这里的软件就是server端的那个程序。(不过也有种说法是,客户端发送错误数据,导致server端保护机制而强制关闭) |