不要尝试使用“特殊”地址,只需在应用程序的内存中设置一个while
循环可以查看的标志,然后connect()
绑定到任何服务器机器的本地 IP 的普通套接字(让connect()
您处理绑定,您不需要bind()
手动调用),例如:
bool shutting_down = false;
.
while (!shutting_down)
{
auto new_connected_socket = accept(listening_socket,...);
// Here it may block for a long time
if (shutting_down)
{
closesocket(new_connected_socket);
break;
}
std::thread(fn_new_connection_handler, new_connected_socket);
}
.
shutting_down = true;
if (server is listening)
{
sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(my server port);
server_addr.sin_addr.s_ddr = inet_addr("127.0.0.1");
SOCKET wakeup_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(wakeup_socket, (sockaddr*)&server_addr, sizeof(server_addr));
closesocket(wakeup_socket);
}
更好的方法是简单地将您的侦听套接字置于非阻塞模式,并select()
在循环中使用超时,以便它可以定期唤醒自己:
while (!shutting_down)
{
fd_set rds;
FD_ZERO(&rds);
FD_SET(listening_socket, &rds);
timeval t;
t.tv_sec = 5;
t.tv_usec = 0;
if ((select(0, &rds, NULL, NULL, &t) > 0) && (!shutting_down))
{
auto new_connected_socket = accept(listening_socket,...);
std::thread(fn_new_connection_handler, new_connected_socket);
}
}
更好的是,使用WSACreateEvent()
andWSAWaitForMultipleEvents()
代替select()
:
WSAEVENT hShutdownEvent = WSACreateEvent();
.
WSAEVENT hAcceptEvent = WSACreateEvent();
WSAEventSelect(listening_socket, hAcceptEvent, FD_ACCEPT);
while (true)
{
WSAEVENT hEvents[2];
hEvents[0] = hAcceptEvent;
hEvents[1] = hShutdownEvent;
DWORD dwRet = WSAWaitForMultipleEvents(2, hEvents, FALSE, INFINITE, FALSE);
if (dwRet == WSA_WAIT_EVENT_0)
{
auto new_connected_socket = accept(listening_socket,...);
std::thread(fn_new_connection_handler, new_connected_socket);
}
else
break;
}
WSACloseEvent(hAcceptEvent);
.
if (server is listening)
WSASetEvent(hShutdownEvent);