gpt4 book ai didi

c++ - 我如何停止/重新开始监听和接受 Winsock2 C++ 中的服务器套接字?

转载 作者:可可西里 更新时间:2023-11-01 17:42:30 25 4
gpt4 key购买 nike

我在 Visual Studio Pro C++ 中制作了一个套接字 (Winsock2) 以监听连接端口 (TCP)。它工作得很好,但我让它在自己的线程中运行,我希望能够关闭它并希望稍后重新启动它。我可以毫无问题地终止线程,但这样做不会阻止套接字接受新客户端(也就是说,它会停留在我关闭线程之前正在执行的接受操作上)。我可以将新客户端连接到它,但什么也没有发生……它只是接受,仅此而已。我想要的是阻止它收听和接受,然后能够告诉它稍后在同一端口上再次启动。现在尝试重新启动它只会告诉我端口已被占用。

监听线程函数如下:

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() 但这两个都抛出了错误。

感谢大家的宝贵时间和帮助!

最佳答案

首先,确保您在服务器套接字上设置了 SO_REUSEADDR 选项,以便能够重新开始监听。

然后,我猜,你的问题是 accept() 阻塞了,你不能在需要的时候停止它,所以你正在杀死线程。糟糕的解决方案。这里的正确答案是异步 I/O,即 select()poll() 或它们的 Windows 对应项。看看Advanced Winsock Samples .

多线程应用程序中的一个快速而肮脏的解决方案是在每个 accept() 之前检查一些 is_it_time_to_stop_accepting_connections 标志,然后在停止时翻转标志并连接到监听端口(是的,在同一个程序中)。这将解锁 accept() 并允许您执行适当的 closesocket() 或其他操作。

但说真的,继续阅读 asynchronous I/O .

关于c++ - 我如何停止/重新开始监听和接受 Winsock2 C++ 中的服务器套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6970394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com