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创建了连接,那么a上面有一个b对应的socket,b上面有一个a对应的socket,两个程序通过各自保存的对方的socket进行通信。如果a通过a上面的socket向b收发消息的时候,b那边的socket已经不存在了,那么a就会收到10053或是10054.从测试来看,如果a里面操作错误的socket,就会触发10054,如果a做了一些其他的操作再操作socket,就会触发10053.

个人猜测

底层导致10053和10054的区别应该是,socket断掉后,会有不同的flag。10054的解释,感觉是被远程reset了,也就是收发消息的这个信号到达了对方,结果在操作的时候,发现已经没了,然后通知回来,告诉你10054的错误。而10053是,我在操作的时候,还没到对方那边,在自己这边就已经知道socket出问题了,于是返回了10053.

猜你喜欢

转载自www.cnblogs.com/studywithallofyou/p/12524167.html