10053 10054
前言
大家在写socket网络通信的时候,最容易碰到的问题就是10053与10054。那么这两个错误是怎么产生的呢?
10053 10054代表什么意思
微软的官方解释如下
10053
WSAECONNABORTED
Software caused connection abort. An established connection was aborted by the software in your host machine, possibly due to a data transmission time-out or protocol error.
10054
WSAECONNRESET
Connection reset by peer. An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, or the remote host uses a hard close (see setsockopt (Windows Sockets) for more information on the SO_LINGER option on the remote socket.) This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
两个的意思差不多,实际测试发现触发的条件也相似,都是因为收发消息的时候,发现对方的socket已经失效,是无效的连接。
有哪些条件可以出发这个情况呢
- 调用closesocket
- 程序直接退出
总而言之,就是对方的socket资源被系统回收了。
测试
测试一
服务端代码,接收到客户端连接就直接closesocket,服务端程序不要退出
SOCKET sserver; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrClient; AddrClient.sin_family = AF_INET; AddrClient.sin_addr.s_addr = INADDR_ANY; AddrClient.sin_port = htons(9999); bind(sserver, (sockaddr*)&AddrClient, sizeof(AddrClient)); listen(sserver, 10); SOCKET sclient = accept(sserver, NULL, NULL); closesocket(sclient);
客户端代码,正常发送接收
int err = 0; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); SOCKET sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrServer; AddrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); AddrServer.sin_port = htons(9999); AddrServer.sin_family = AF_INET; connect(sserver, (SOCKADDR *)&AddrServer, sizeof(SOCKADDR)); char temp[] = "hello server"; int rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; char buff[1024] = { 0 }; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl;
输出
0 10054 10054 10054
服务端在建立好连接后,直接关闭了socket,客户端这边在第一次发送的时候,应该是由于比较快,认为现在还是正常的,发送到了缓冲区,是正常的。在后面接收发送的时候,发现socket有问题了,报了10054的错误。
测试二
服务端程序,建立好连接后,并没有调用closesocket,而是直接程序退出了
SOCKET sserver; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrClient; AddrClient.sin_family = AF_INET; AddrClient.sin_addr.s_addr = INADDR_ANY; AddrClient.sin_port = htons(9999); bind(sserver, (sockaddr*)&AddrClient, sizeof(AddrClient)); listen(sserver, 10); SOCKET sclient = accept(sserver, NULL, NULL);
return;
客户端程序,与上面一样,正常接收发送
int err = 0; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); SOCKET sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrServer; AddrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); AddrServer.sin_port = htons(9999); AddrServer.sin_family = AF_INET; connect(sserver, (SOCKADDR *)&AddrServer, sizeof(SOCKADDR)); char temp[] = "hello server"; int rs = 0; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; char buff[1024] = { 0 }; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl;
输出
0 10054 10054 10054
可以看到,程序直接退出,与closesocket是一样的现象。
测试三
服务端socket连接成功后就close,但是程序不退出
SOCKET sserver; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrClient; AddrClient.sin_family = AF_INET; AddrClient.sin_addr.s_addr = INADDR_ANY; AddrClient.sin_port = htons(9999); bind(sserver, (sockaddr*)&AddrClient, sizeof(AddrClient)); listen(sserver, 10); SOCKET sclient = accept(sserver, NULL, NULL); closesocket(sclient);
客户端正常接收,只不过在连接成功后,sleep一会
int err = 0; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); SOCKET sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrServer; AddrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); AddrServer.sin_port = htons(9999); AddrServer.sin_family = AF_INET; connect(sserver, (SOCKADDR *)&AddrServer, sizeof(SOCKADDR)); Sleep(1000); char temp[] = "hello server"; int rs = 0; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; char buff[1024] = { 0 }; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl;
输出
0 10053 10053 10053
结果变成了10053,与测试一唯一的区别就是增加了sleep
测试四
服务端连接成功后,直接退出程序
SOCKET sserver; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrClient; AddrClient.sin_family = AF_INET; AddrClient.sin_addr.s_addr = INADDR_ANY; AddrClient.sin_port = htons(9999); bind(sserver, (sockaddr*)&AddrClient, sizeof(AddrClient)); listen(sserver, 10); SOCKET sclient = accept(sserver, NULL, NULL); closesocket(sclient); return;
客户端还是建立连接后,sleep一会,然后再正常收发消息
int err = 0; WORD VersionRequested; WSADATA WsaData; VersionRequested = MAKEWORD(2, 2); WSAStartup(VersionRequested, &WsaData); SOCKET sserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN AddrServer; AddrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); AddrServer.sin_port = htons(9999); AddrServer.sin_family = AF_INET; connect(sserver, (SOCKADDR *)&AddrServer, sizeof(SOCKADDR)); Sleep(1000); char temp[] = "hello server"; int rs = 0; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; char buff[1024] = { 0 }; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = send(sserver, temp, sizeof(temp) + 1, 0); err = WSAGetLastError(); std::cout << err << std::endl; rs = recv(sserver, buff, sizeof(buff), 0); err = WSAGetLastError(); std::cout << err << std::endl;
输出
0 10053 10053 10053
总结
触发10053/10054的条件就是,a与b创建了socket连接,如果a通过socket向b收发消息的时候,b那边的连接已经不存在了,a就会收到10053或是10054。从测试来看,如果socket断开后立马操作,就会触发10054,如果做了一些其他的事情再操作,就会触发10053.
10053和10054的区别是,socket异常后,会有一个fin消息,如果在这个消息到达之前就reset,就会触发10054;如果这个消息已经到达,再reset,就会触发10053.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏