关机失败,错误 10038

Shutdown failed with error 10038

我正在制作一个 Winsock 应用程序,当服务器试图执行关闭功能时出现了故障。项目构建并运行,但是当客户端的第一个连接到达时,它接受它并且在命令行中显示失败: "shutdown failed with error: 10038"。 我一直在阅读有关该错误的信息,据说这通常是因为功能关闭应用于不是 SOCKET 或类似的东西。但是调试的时候看到明明是Socket,不知道怎么办。

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include "stdafx.h"

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
//Function declaration
const std::string currentDateTime();
int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket, char *recvbuf,  int recvbuflen, int iSendResult, int iResult);
std::string CommandGet(char *recvbuf);
void Login(char *recvbuf);
void print_data(char *recvbuf);
string GetUsername(char *recvbuf);
string GetThirdToken(char *recvbuf);

//Map & Struct creation
struct message{
    static unsigned int last_id;
    unsigned int id;
    std::string baa;
    std::string timestamp;
    message(){};
    message(const std::string& recvbuf_baa,const std::string& a_timestamp) :
    baa(recvbuf_baa), timestamp(a_timestamp), id(++last_id)
  {
  }
};
map<std::string,std::vector<message *> > data;
map<std::string,std::vector<string> > followers;
//Global variables
unsigned int message::last_id = 0;
map<std::string,bool> loggedin;

int __cdecl main(void) 
{
    WSADATA wsaData;
    int iResult;

    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo *result = NULL;
    struct addrinfo hints;



    int iSendResult=0;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;
    while(true){
        // Resolve the server address and port
        iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
        if ( iResult != 0 ) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }

        // Create a SOCKET for connecting to server
        ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
        if (ListenSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            freeaddrinfo(result);
            WSACleanup();
            return 1;
        }

        // Setup the TCP listening socket
        iResult = ::bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            printf("bind failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }

        freeaddrinfo(result);

        iResult = listen(ListenSocket, SOMAXCONN);
        if (iResult == SOCKET_ERROR) {
            printf("listen failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
        // Accept a client socket
        ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ClientSocket == INVALID_SOCKET) {
            printf("accept failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }

        // No longer need server socket
        closesocket(ListenSocket);

         return NewClient(ListenSocket, ClientSocket, recvbuf, recvbuflen, iSendResult, iResult);



    }
}

int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket,  char *recvbuf,  int recvbuflen, int iSendResult, int iResult){



        // Receive until the peer shuts down the connection
        do {
            iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
            if (iResult > 0) {
                printf("Bytes received: %d\n", iResult);
                std::string cmd=CommandGet(recvbuf);
                if (cmd=="log"){
                    std::string usrn=GetUsername(recvbuf);
                    std::string recvbuf_str="";
                    for(auto it=loggedin.begin();it!=loggedin.end();it++){
                        if ((*it).first==usrn){
                            recvbuf_str="loggedin";
                            if ((*it).second){
                                recvbuf_str="cantlogin";
                                break;
                            }
                            else{
                                loggedin[usrn]=1;
                                break;
                            }
                            break;
                        }
                    }
                    if (recvbuf_str==""){
                        recvbuf_str="newlogin";
                        Login(recvbuf);
                    }
                    iSendResult = send( ClientSocket, recvbuf_str.c_str(), iResult, 0 );
                    if (iSendResult == SOCKET_ERROR) {
                        printf("send failed with error: %d\n", WSAGetLastError());
                        closesocket(ClientSocket);
                        WSACleanup();
                          return 1;
                    }
                }


            }

            else if (iResult == 0){
                printf("Connection closing...\n");
                closesocket(ClientSocket);}
            else  {
                printf("recv failed with error: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                  return 1;
            }

        } while (iResult > 0);


    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    // cleanup
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
}
const std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    localtime_s(&tstruct, &now);
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
    return buf;
}

void Login(char *recvbuf){
    std::string usrn= GetUsername(recvbuf);
    std::vector<message *> messages;
    data[usrn]=messages;
    std::vector<string> follow;
    followers[usrn]=follow;
    loggedin[usrn]=1;
}


void print_data(char *recvbuf){
    std::string usrn= GetUsername(recvbuf);

    for(auto mapIt = data.cbegin(); mapIt != data.cend(); ++mapIt)
    {
    std::cout << "printing data for " << mapIt->first << ":" << std::endl;
    for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
        {
            std::cout << (*vectIter)->baa << ", " << (*vectIter)->timestamp << ", "
                  << (*vectIter)->id << std::endl;
        }
    }
}

void print_followers(char *recvbuf){
    std::string usrn= GetUsername(recvbuf);

    for(auto mapIt = followers.cbegin(); mapIt != followers.cend(); ++mapIt)
    {
    std::cout << "printing followers for " << mapIt->first << ":" << std::endl;
    for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
        {
            std::cout << (*vectIter) << endl;
        }
    }
}

std::string CommandGet(char *recvbuf){
        int start0=0;
        std::string recvbuf_cmd;
        std::string recvstr(recvbuf);
        start0=recvstr.find(';');
        recvbuf_cmd=recvstr.substr(0,start0);
        return recvbuf_cmd;
}

string GetUsername(char *recvbuf){
    int start0=0, start1=0;
    std::string recvbuf_usrn;
    std::string recvstr(recvbuf);
    start0=recvstr.find(';');
    start1=recvstr.find(';',start0+1);
    recvbuf_usrn=recvstr.substr(start0+1,start1-start0-1);
    return recvbuf_usrn;
}

string GetThirdToken(char *recvbuf){
    int start0=0, start1=0, start2=0;
    std::string recvbuf_thirdtoken;
    std::string recvstr(recvbuf);
    start0=recvstr.find(';');
    start1=recvstr.find(';',start0+1);
    start2=recvstr.find(';',start1+1);
    recvbuf_thirdtoken=recvstr.substr(start1+1,start2-start1-1);
    return recvbuf_thirdtoken;
}

我上传了整个项目,以防你想更深入地检查它(https://mega.nz/#!dtcx1DCL!dKWV2ryDDfiXv5H3Mi2p4PrBpie2CGrGJOTAwvQAV8M),但问题出在服务器上(我简化了代码),客户端只是这样你就可以开始了输入用户名的连接(但不关心它)。

提前致谢,如有任何帮助,我们将不胜感激。

让我们考虑以下几行,取自您显示的来源:

iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
...
else if (iResult == 0){
    printf("Connection closing...\n");
    closesocket(ClientSocket);}
...
iResult = shutdown(ClientSocket, SD_SEND);

recv returns zero that means the connection has been closed (nicely) by the other end. When that happens you call closesocket to close the socket. But then you proceed to unconditionally call shutdown关闭套接字时,导致你得到的错误。

简单的解决方案?只需使用closesocket 一次关闭套接字,不需要shutdown这里我可以看到(很少有)。