Socket error 10053,10054究竟是怎么引起的


REFER TO: http://bbs.csdn.net/topics/360024280

Q: 誰能貼點代碼,能穩定的重現這2個socket error嗎?我就是想知道,出現這2個問題時,TCP協議棧到底遇到什么異常情況了。貼2段能穩定重現10053的代碼。

先貼客戶端的:

    WORD    VersionRequested;
    WSADATA WsaData;

    VersionRequested = MAKEWORD(2, 2);

    if (WSAStartup(VersionRequested, &WsaData))
        return -1;

    SOCKET SocketServer  = 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;

    // 連接服務器
    if (0 != connect(SocketServer, (SOCKADDR *)&AddrServer, sizeof(SOCKADDR)))
    {
        closesocket(SocketServer);
        return false;
    }

    int err = 0;
    char temp[] = "hello, server";
    int rs = send(SocketServer, temp, sizeof(temp) + 1, 0);

    char buff[1024] = {0};
    rs = recv(SocketServer, buff, sizeof(buff), 0);

        // 下面這2句代碼如果注釋掉,后面的recv就能正解的返回0。如果不注釋掉,recv就會返回-1,
         // 並得到10053這個錯誤
    rs = send(SocketServer, temp, sizeof(temp) + 1, 0);
    err = WSAGetLastError();

    rs = recv(SocketServer, buff, sizeof(buff), 0);
    err = WSAGetLastError();

    system("pause");
    return 0;

這個是服務器的

    WORD    VersionRequested;
    WSADATA WsaData;

    VersionRequested = MAKEWORD(2, 2);

    if (WSAStartup(VersionRequested, &WsaData))
    {
        printf("加載socket庫失敗!\n");
        return -1;
    }

    // 監聽來自瀏覽器的請求
    SOCKET SockServer = 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);

    if (SockServer == INVALID_SOCKET)
    {
        printf("socket初始化失敗!\n");
        closesocket(SockServer);
        WSACleanup();
        return -1;
    }

    if (bind(SockServer, (sockaddr*)&AddrClient, sizeof(AddrClient)) != 0)
    {
        printf("socket綁定失敗!\n");
        closesocket(SockServer);
        WSACleanup();
        return -1;
    }

    if (listen(SockServer, 10) != 0)
    {
        printf("socket監聽失敗!\n");
        closesocket(SockServer);
        WSACleanup();
        return -1;
    }

    while (1)
    {
        SOCKET NewSocket = accept(SockServer, NULL, NULL);
        if (INVALID_SOCKET == NewSocket)
        {
            closesocket(NewSocket);
            continue;
        }
        else
        {
            struct linger so_linger;
            so_linger.l_onoff  = 1;
            so_linger.l_linger = 30;
            setsockopt(NewSocket ,SOL_SOCKET, SO_LINGER, (const char*)&so_linger, sizeof(so_linger)); 
        }

        char buff[1024];
        int rs = recv(NewSocket, buff, sizeof(buff), 0);

        char temp[] = "hello, client";
        rs = send(NewSocket, temp, sizeof(temp) + 1, 0);

        closesocket(NewSocket);
    }

A:出現10053的原因是因為在你執行這次send的時候對端已經執行過closesocket了,而發送的數據還是被成功的推入了發送緩沖區中,因此返回了0,此時你可能還沒得到FIN消息,而緊接着recv這邊就得到了對端關閉socket的FIN消息,因此此時需要放棄發送緩沖中的數據,異常終止連接,所以得到了10053錯誤:您的主機中的軟件中止了一個已建立的連接。

而為什么又能得到10054的錯誤號,原因應該在於你設置了SO_LINGER了,一但設置了它,則有一個等待時間,在該等待時間內可以處理發送緩沖區的數據,一但超時或者發送緩沖都被發送完並被確認,則服務端有可能發送RST消息而不是FIN,此時客戶端就應該得到重置錯誤,也就是10054。

不同的系統對SO_LINGER的實現方式不一樣,得到的結果也不一樣,不知道按我這樣解釋是否對你有幫助。如果我有理解錯誤,歡迎大家指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM