Winsock 10053错误分析

简介:

 WSAGetLastError可能会返回10053错误,查msdn的解释是:

WSAECONNABORTED 10053

Software caused connection abort.

An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.

神马?软件原因造成的连接中断,这是什么意思,不跟没说一样的么?
google一下呗

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不能接收更多的连接了。
这还不如不说,越说越糊涂了。
winsocket的描述,似乎还靠谱一些,这种错误一般发生在一个建立的连接被重发失败的情况下产生,接收方没有响应数据发回来。但还是比较模糊。
再看看tcp ip标准文档的说法,如果本地系统没有收到发送数据的响应(ack)那么这连接就会超时。如果tcp的fin包没有被ack(或者fin包被ack了但fin没有返回)那么也会超时。但是,但是,超时跟这个10053有神马关系?
再看后续的解释:
从参考1中找到如下的描述:

The Scenario: 
An HTTP POST is to be sent to an HTTP server.
The server begins reading the POST and notices that the HTTP request header is invalid.
It immediately sends an HTTP response (with an error status, perhaps status=400) and closes the connection without trying to continue reading the remainder of the HTTP request that is forthcoming.

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.)
The client finishes writing the HTTP POST to the socket — meaning that data has been buffered to Winsock. The client application then tries to read the HTTP response, but it cannot because the outgoing retransmission (of the buffered data by WinSock) failed and the socket connection was shutdown on the client side (by Winsock). Even though the HTTP server sent the response, it is lost and cannot be retrieved. The error your application will receive when
trying to read the HTTP response on the socket is WSAECONNABORTED. The word "software" in any of the above error messages refers to "WinSock".

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抓包

整个通信过程如下:
1-3.三次握手建立连接
4.客户端(10.10.86.93)向服务器端(10.10.86.98)发送数据,1字节
5.server 中止 发送fin(同时ack之前那个push)
6.client ack 那个fin
7.client再发送两个字节
8.server此时已经关闭socket,属于非正常情况,回复复位命令

整个过程可以重现10053情况,tcp发送分组数据的情况也一目了然,事情到此就可以了么?显然不是,你也看到了后面还有很多文字,不知此时你心中的问题是否跟我一样,先说我自己的吧,通过抓包发现这里的异常关闭有个reset,但reset一般是10054(Connection reset by peer)的错误,那么10053与10054的区别在哪里。要搞清楚问题也不难,重现场景抓包分析。
以下是修改上面的cs程序,在client发送的1字节包后,立即crash,这导致的问题是操作系统会立即回收所有资源,包括socket资源。




图4 10054错误client端tcp状态流转

可以看到在crash之前这个tcp都是established状态。crash之后,client端接收数据时会收到10054错误,场景重现了,我们再看一下抓包情况



图5 10054错误client端tcp抓包

这个抓包情况跟10053很像,1-7也同10053,在8时,client收到server发过来的reset,表示当前连接被强制复位了。
对比10053和10054可以发现,如果srv返回fin标志后再reset那么对应的错误就是10053,如果直接reset就是10054错误。回过头来在看参考2中的说法也就有点感觉了。

总结一下:
1.遇到不了解的问题,google是非常好的方法
2.对于一般问题,重现之很重要,可以反复发现问题并验证问题。自己写程序或者搭环境尽量重现。
3.网络问题抓包是利器,包括各种工具的使用netstat wireshark ping traceroute等。
4.多重问题对比其中的差异,这里对比10053错误和10054错误。
5.理论基础要搭好,本次问题主要是tcp的异常断开问题,熟悉tcp断开的半关闭和复位逻辑,不过理论还是理论,同样是复位在不同场景下的错误码不同。并且实现上也跟具体的操作系统相关。
6.实际工作中,
10053错误时,用户主要是处于透明代理情况,那么这一般是又有用户所在的代理服务器异常关闭导致的,可能跟我们的离线文件私有协议被用户所在的代理服务器拒绝掉导致的。

7.回过头来在看一开始的解释,所谓软件原因造成的连接终端,就是本例子中,server端在shoutdown本方向传输时,立即关闭了socket,导致本应该等待对方发送fin来完全结束的正常逻辑被打破,编程单方向强制中止本次tcp,导致client端之后向上报错,就是所谓的10053错误了,这里的软件就是server端的那个程序。(不过也有种说法是,客户端发送错误数据,导致server端保护机制而强制关闭)

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
7月前
|
存储
调试实战——使用windbg调试崩溃在ole32!CStdMarshal::DisconnectSrvIPIDs
使用windbg调试崩溃在ole32!CStdMarshal::DisconnectSrvIPIDs
|
9月前
|
安全 Windows
4.4 x64dbg 绕过反调试保护机制
在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,我们以第一种`IsDebuggerPresent`反调试为例,该函数用于检查当前程序是否在调试器的环境下运行。函数返回一个布尔值,如果当前程序正在被调试,则返回True,否则返回False。函数通过检查特定的内存地址来判断是否有调试器在运行。具体来说,该函数检查了`PEB(进程环境块)`数据结构中的`_PEB_LDR_DATA`字段,该字段标识当前程序是否处于调试状态。如果该字段的值为1,则表示当前程序正在被调试,否则表示当前程序没有被调试。
159 0
4.4 x64dbg 绕过反调试保护机制
|
11月前
|
编解码 缓存 C++
C++ <windows.h>库函数探究初步:句柄操作
C++ <windows.h>库函数探究初步:句柄操作
9604 0
|
Java 编译器 C++
JNI编程怎么跟踪调试dll?
本文主要讲解一下在jni开发中,如何调试C/C++编写的DLL模块。
370 0
JNI编程怎么跟踪调试dll?
|
安全 Windows
IAR故障解决:由于找不到mfc140u.dll,无法继续执行代码
IAR故障解决:由于找不到mfc140u.dll,无法继续执行代码
IAR故障解决:由于找不到mfc140u.dll,无法继续执行代码
|
Windows 数据格式 XML