2016-04-21 13 views
0

Ich mache eine Winsock-Anwendung, und etwas schlägt auf dem Server fehl, wenn es versucht, die Shutdown-Funktion zu machen. Das Projekt wird erstellt und ausgeführt, aber wenn die erste Verbindung des Clients eintrifft, nimmt es es und schlägt fehl in der Befehlszeile: "shutdown failed with error: 10038". Ich habe über den Fehler gelesen und es wird gesagt, dass es in der Regel ist, weil die Funktion Herunterfahren auf etwas angewendet wird, das kein SOCKET oder so ist. Aber beim Debuggen habe ich gesehen, dass es anscheinend ein Socket ist, also weiß ich nicht, was ich tun soll.Herunterfahren fehlgeschlagen mit Fehler 10038

#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; 
} 

ich laden das gesamte Projekt, falls Sie es überprüfen wollen tiefer (https://mega.nz/#!dtcx1DCL!dKWV2ryDDfiXv5H3Mi2p4PrBpie2CGrGJOTAwvQAV8M), aber das Problem in dem Server befindet (was ich den Code vereinfacht), ist der Kunde nur so können Sie die conection starten Geben Sie den Benutzernamen ein (aber kümmern Sie sich nicht darum).

Vielen Dank im Voraus, jede Hilfe wird geschätzt.

+0

Geben Sie uns nicht "das ganze Projekt", vor allem als ein Link, der schal werden kann und die ganze Frage wertlos macht. Versuchen Sie stattdessen, ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) zu erstellen, um uns * im Fragenhauptteil * anzuzeigen. und wenn Sie Probleme haben, dann extrahieren Sie die relevanten Teile aus dem tatsächlichen Code und zeigen Sie uns, * auch * im Körper der Frage. Und wenn Sie dies noch nicht getan haben, lesen Sie bitte [wie Sie gute Fragen stellen können] (http://stackoverflow.com/help/how-to-ask). –

+0

@JoachimPileborg danke für deine Antwort, ich habe die Frage bearbeitet, um den Servercode direkt in der Frage anzugeben. – 19mike95

Antwort

2

Hier können Sie die folgenden Zeilen betrachten, nehmen Sie aus Ihrer gezeigten Quelle:

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

Wenn recv kehrt Null, die die Verbindungsmittel hat (gut) mit dem anderen Ende geschlossen. Wenn das passiert, rufen Sie closesocket, um den Socket zu schließen. Aber dann fahren Sie fort, bedingungslos shutdown auf dem geschlossenen Sockel zu rufen, was zu dem Fehler führt, den Sie haben.

Einfache Lösung? Schließen Sie einfach die Steckdose mit closesocketeinmal, keine Notwendigkeit für shutdown hier, dass ich sehen kann (gibt es selten).

+0

danke für deine antwort, ich habe es versucht, aber wenn ich das mache, wird der server geschlossen, wenn die erste verbindung beendet ist, und ich möchte immer noch auf den nächsten befehl hören, was kann ich tun? – 19mike95

+0

@ 19mike95 Das ist ein ganz anderes Problem, und um das zu lösen, sollten Sie sich die Logik in Ihrer Hauptfunktion genauer ansehen. Wenn Sie Ihren eigenen Code nicht manuell verfolgen können, schlage ich vor, dass Sie ihn in einem Debugger zeilenweise durchlaufen. Wenn Sie nicht wissen, wie Sie es beheben können, ist es das Thema für eine andere Frage. –

Verwandte Themen