在退出时,主线程依次调用 shutdown 和 closesocket 良好的关闭 accept 对应的 socket,此时 accept 工作线程中 accept 函数会返回 INVALID_SOCKET。
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
SOCKET listen_socket;
bool Init(unsigned short listen_port)
{
SOCKADDR_IN local;
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket == INVALID_SOCKET)
{
return false;
}
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(listen_port);
if (bind(listen_socket, (sockaddr *)&local, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
closesocket(listen_socket);
listen_socket = INVALID_SOCKET;
return false;
}
if (listen(listen_socket, 32) == SOCKET_ERROR)
{
closesocket(listen_socket);
listen_socket = INVALID_SOCKET;
return false;
}
return true;
}
DWORD WINAPI AcceptThreadProc(LPVOID param)
{
while (!*(bool *)param)
{
sockaddr_in remote_addr;
int addr_len = sizeof(sockaddr);
printf("accept start\n");
SOCKET sock = accept(listen_socket, (sockaddr *)&remote_addr, &addr_len);
printf("socket = %d\n", sock);
}
return 0;
}
int main()
{
WSADATA wsa_data;
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
{
return 0;
}
if (Init(9999))
{
bool stop = false;
HANDLE accept_thread = CreateThread(0, 0, AcceptThreadProc, &stop, 0, 0);
if (accept_thread != NULL)
{
system("pause");
}
stop = true;
shutdown(listen_socket, SD_BOTH);
closesocket(listen_socket);
WaitForSingleObject(accept_thread, INFINITE);
CloseHandle(accept_thread);
accept_thread = NULL;
}
WSACleanup();
return 0;
}
联系客服