我在Visual Studio Pro C ++中创建了一个套接字(Winsock2)来监听端口上的连接(TCP)。它工作得很好,但我让它在自己的线程中运行,我希望能够关闭它,希望以后重新启动它。我可以毫无问题地终止线程,但这样做并不会阻止套接字接受新的客户端(也就是说,它在我关闭线程之前依赖于它正在进行的接受)。我可以将新客户连接到它但没有任何反应......它只是接受而且就是这样。我想要的是阻止它听取和接受,然后能够告诉它稍后在同一个端口再次启动。现在尝试重新启动它只是告诉我端口已经被占用。
这是listen thread函数:
DWORD WINAPI ListeningThread(void* parameter){
TCPServer *server = (TCPServer*)parameter;
try{
server = new TCPServer(listen_port);
}catch(char* err){
cout<<"ERROR: "<<err<<endl;
return -1;
}
int result = server->start_listening();
if(result < 0){
cout<<"ERROR: WSA Err # "<<WSAGetLastError()<<endl;
return result;
}
cout<<"LISTENING: "<<result<<endl<<endl;
while(true){
TCPClientProtocol *cl= new TCPClientProtocol(server->waitAndAccept());
HANDLE clientThread = CreateThread(0, 0, AcceptThread, cl, 0, 0);
cout<<"Connection spawned."<<endl;
}
return 0;
}
以下是TCPServer中的相关功能:
TCPServer::TCPServer(int port){
listening = false;
is_bound = false;
//setup WSA
int result = WSAStartup(MAKEWORD(2, 2), (LPWSADATA) &wsaData);
if(result < 0){
throw "WSAStartup ERROR.";
return;
}
//create the socket
result = (serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP));
if(result < 0){
throw "Socket Connect ERROR.";
return;
}
//bind socket to address/port
SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = INADDR_ANY;
result = bind(serverSocket, (LPSOCKADDR) &sin, sizeof(sin));
if(result < 0){
throw "Could not Bind socket - Make sure your selected PORT is available.";
return;
}
is_bound = true;
}
int TCPServer::start_listening(){
int result = -1;
if(is_bound){
//SOMAXCONN parameter (max) is a backlog:
// how many connections can be queued at any time.
result = listen(serverSocket, SOMAXCONN);
if(result >= 0)
listening = true;
}
return result;
}
SOCKET TCPServer::waitAndAccept(){
if(listening)
return accept(serverSocket, NULL, NULL);
else
return NULL;
}
我已尝试过closesocket()和shutdown(),但这两个都引发了错误。
感谢大家的时间和帮助!
答案 0 :(得分:9)
首先,确保在服务器套接字上设置SO_REUSEADDR
选项才能重新开始监听。
然后,我猜,你的问题是accept()
阻塞,你不能在需要时阻止它,所以你要杀死线程。解决方案不好这里正确的答案是异步I / O,即select()
或poll()
或它们的Windows对应物。看看Advanced Winsock Samples。
多线程应用程序中的快速解决方案是在每个is_it_time_to_stop_accepting_connections
之前检查一些accept()
标志,然后在需要停止时,翻转标志并连接到侦听端口(是,在同一个程序中)。这将取消阻止accept()
并允许您执行正确的closesocket()
或其他任何操作。
但严重的是,请阅读asynchronous I/O。