Winsock - 客户端断开连接,关闭套接字循环/最大连接数
Posted
技术标签:
【中文标题】Winsock - 客户端断开连接,关闭套接字循环/最大连接数【英文标题】:Winsock - Client disconnected, closesocket loop / maximum connections 【发布时间】:2015-07-18 23:04:25 【问题描述】:我正在学习 Winsock,并尝试创建一些简单的程序来了解它。我设法创建了可以处理多个连接的服务器,还根据所有教程管理它们和客户端,它正在按预期工作,但是:
我尝试创建循环,检查是否有任何客户端断开连接,如果断开连接,我想关闭它。
我设法编写了一些东西来检查套接字是否已断开连接,但它不会同时连接 2 个或多个套接字
如果每个客户端已断开并关闭套接字,任何人都可以给我答复如何通过每个客户端进行工作循环检查?这一切都是为了让最大客户端一次连接到服务器。提前致谢。
while (true)
ConnectingSocket = accept (ListeningSocket, (SOCKADDR*)&addr, &addrlen);
if (ConnectingSocket!=INVALID_SOCKET)
Connections[ConnectionsCounter] = ConnectingSocket;
char *Name = new char[64];
ZeroMemory (Name,64);
sprintf (Name, "%i",ConnectionsCounter);
send (Connections[ConnectionsCounter],Name,64,0);
cout<<"New connection !\n";
ConnectionsCounter++;
char data;
if (ConnectionsCounter>0)
for (int i=0;i<ConnectionsCounter;i++)
if (recv(Connections[i],&data,1, MSG_PEEK))
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
Sleep(50);
【问题讨论】:
How can I check is a socket is still open? 的可能重复项 您提供的示例代码没有提供足够的细节来提供帮助。提供的代码部分是循环调用的函数吗?您在调试器中看到了什么? @advent 为什么拒绝我对您的示例代码的编辑?它的格式不可读。 我不认为这是必要的编辑。它是完整的代码,无需声明套接字、绑定和侦听。我将添加整个循环。 可能对你有用:msdn.microsoft.com/en-us/library/windows/desktop/… 【参考方案1】:您似乎想使用单个线程管理多个连接。对? 简单来说socket通信有两种方式,阻塞和非阻塞。默认是块模式。让我们专注于您的代码:
for (int i=0;i<ConnectionsCounter;i++)
if (recv(Connections[i],&data,1, MSG_PEEK))
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
在上面的代码中,您调用了 recv 函数。它将阻塞,直到对等方向您发送消息,或对等方关闭链接。因此,如果您现在有两个连接,即 Connections[0] 和 Connections[1]。如果你是recv Connections[0],同时Connections[1] 断开了,你不知道。因为您在 recv(Connections[0]) 处阻塞。当 Connections[0] 向您发送消息或关闭套接字时,然后循环继续,最后您检查它是否断开连接,即使它在 10 分钟前断开连接。
要解决这个问题,我认为您需要一本书Microsoft Windows 网络编程。有一些方法,例如一线程一套接字模式、异步通信模式、非阻塞模式等。
忘了指出bug,这里注意一下:
closesocket(Connectons[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
让我举一个例子来说明它。现在我们有两个索引为 0 和 1 的连接,那么 ConnectionsCount 应该是 2,对吧?当 Connections[0] 断开连接时,ConnectionsCounter 从 2 变为 1。并且循环退出,新客户端连接,您将新客户端套接字保存为 Connections[ConnectionsCounter(=1)] = ConnectingSocket;哎呀,有一个错误。因为断开连接的套接字的索引是 0,而索引 1 被另一个链接使用。您正在重用索引 1。
为什么不尝试使用矢量来保存套接字。
希望对你有帮助~
【讨论】:
是的,我使用的是单线程。我成功了,但我在这个多重连接检查中遗漏了一些东西。使用 recv 使我的服务器只能专注于单个客户端,而其他客户端必须等到另一个客户端关闭。 这就是我的想法,我看到类 Socket 有一个名为 isDisconnected 的方法或类似的方法,所以使用它可能是个好主意。我还有很多东西要学,我也有很多想法如何尝试实现这些和其他东西,但我需要一些时间才能理解它是如何工作的并能够流利地处理它。感谢您的关注和良好的建议,这真的很有帮助。 从头到尾完全不正确。如果在您检查这个时另一个对等方断开了连接,您稍后会在检查时发现它。断开连接事件不仅被丢弃。检测对等断开连接的唯一方法是尝试从套接字读取。没有其他套接字方法可以告诉您这一点。不要在这里发布错误信息。 是否有冲突?如果线程在等待recv(connections[0]...)返回,而connections[1]断开,此时程序并不知道,直到connections[ 0] 发送数据或断开连接然后循环继续到 recv(connections[1]...) 并返回 -1,现在我们知道连接 [1] 断开连接。有什么问题吗? 实际上循环正在工作,即使它正忙于其他套接字。如果我快速关闭 10 个客户端,在关闭繁忙的客户端后,我会收到 11 个断开连接,连接消息。以上是关于Winsock - 客户端断开连接,关闭套接字循环/最大连接数的主要内容,如果未能解决你的问题,请参考以下文章