我使用Win32 API创建了一个窗口,它需要输入一个消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
如果主线程处理UI消息,如何创建套接字服务器并开始接收客户端?
我尝试使用CreateThread()
中的WinMain()
将所有服务器代码放入一个帖子中,但它只是因为错误而崩溃:
test.exe中0x00000000处抛出异常:0xC0000005:访问冲突执行位置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;
}
答案 0 :(得分:0)
这是一个非常令人困惑的问题,因为它在标题中提出了一个问题,但内容解决了另一个问题(线程崩溃)。
解决主要问题:Microsoft确实添加了一种以GUI线程友好的方式处理套接字通信的方法:WSAAsyncSelect。这会将套接字事件作为消息发送到应用程序消息队列 - 通常会创建一个不可见的窗口来处理消息。