2016-11-16 67 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消息?”这是 - 毫无疑问 - 然后跟随了大量关于线程的噪音。 –