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已经失效,是无效的连接。

有哪些条件可以出发这个情况呢

  1. 调用closesocket
  2. 程序直接退出

总而言之,就是对方的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.

posted @   秋来叶黄  阅读(465)  评论(0编辑  收藏  举报
编辑推荐:
· 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的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示