2016-11-16 66 views
-4

我做了使用Win32 API的窗口,它需要進入一個消息循環:的Windows消息循環和服務器循環

while (GetMessage(&msg, nullptr, 0, 0)) 
{ 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

如何創建一個套接字服務器,並開始接待客戶,如果我的主線程處理UI消息?

我試圖把所有的服務器代碼的使用從WinMain()CreateThread()一個線程,但它只是一個錯誤崩潰:

Exception thrown at 0x00000000 in test.exe: 0xC0000005: Access violation executing location 0x00000000.

這裏是線程代碼:

DWORD WINAPI ThreadProc(LPVOID lpParameter) 
{ 
    // Initialize Winsock 
    WSADATA wsaData; 
    auto iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (iResult != 0) { 
     printf("WSAStartup failed with error: %d\n", iResult); 
     return EXIT_FAILURE; 
    } 

    addrinfo hints; 
    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_INET; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 
    hints.ai_flags = AI_PASSIVE; 

    // Resolve the server address and port 
    PADDRINFOA pAddrInfo = nullptr; 
    iResult = getaddrinfo(nullptr, PORT, &hints, &pAddrInfo); 
    if (iResult != 0) { 
     printf("getaddrinfo failed with error: %d\n", iResult); 
     WSACleanup(); 
     return EXIT_FAILURE; 
    } 

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

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

     freeaddrinfo(pAddrInfo); 

     iResult = listen(ListenSocket, SOMAXCONN); 
     if (iResult == SOCKET_ERROR) { 
      printf("listen failed with error: %d\n", WSAGetLastError()); 
      closesocket(ListenSocket); 
      WSACleanup(); 
      return EXIT_FAILURE; 
     } 

     // Accept a client socket 
     auto ClientSocket = accept(ListenSocket, nullptr, nullptr); 
     if (ClientSocket == INVALID_SOCKET) { 
      printf("accept failed with error: %d\n", WSAGetLastError()); 
      closesocket(ListenSocket); 
      WSACleanup(); 
      return EXIT_FAILURE; 
     } 

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

     // Receive until the peer shuts down the connection 
     for (;;) 
     { 
      char recvbuf[1] = { 0 }; 
      auto cbLen = recv(ClientSocket, recvbuf, sizeof(recvbuf), 0); 

      if (cbLen > 0) { 
       if (recvbuf[0] == 0xDA) 
       { 
        Hide(); 
       } 

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

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

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

    return 0; 
} 
+1

什麼是你的代碼的其餘部分(我不能看到ThreadProc的和CreateThread的)?你在哪裏得到例外? – z32a7ul

+0

我看到異常拋出在0x00000000 - 是你的ThreadProc NULL?我的意思是當你調用CreateThread時,參數的確切值告訴新線程的起始地址是什麼? – z32a7ul

+0

有一個在你的代碼中的缺陷,但你沒有表現出任何相關的代碼 –

回答

0

這是一個非常令人困惑的問題,因爲它在標題中提出了一個問題,但內容解決了另一個問題(線程崩潰)。

要解決的首要問題:微軟確實添加了一種方法來處理在GUI線程友好的方式socket通信:WSAAsyncSelect。這會將套接字事件作爲消息發送到應用程序消息隊列 - 通常會創建一個不可見窗口來處理消息。

+0

提問者可能要求你寫這個答案,但它不回答問題。 –

+0

這是在後一個問題的第一個實際線路是從字面上:「我如何創建一個套接字服務器,並開始接待客戶,如果我的主線程處理UI消息?」這是 - 毫無疑問 - 然後跟隨了大量關於線程的噪音。 –