C& linux:重用封闭的套接字/替代品

时间:2016-04-27 17:03:42

标签: c linux sockets file-descriptor

我正在为游戏制作多线程tcp服务器。

我遇到套接字问题,当服务器停止从客户端收到信息时,我关闭了我接受的套接字()(如下所示)并退出线程并通知主线程插槽不忙了。

clientData.client[next] ) = accept(server,(struct sockaddr *)&client_address,&t)); 

(错误检查在这里省略但我确实有)

然而,当我再次尝试进入该插槽时,它给了我一个糟糕的文件描述符,我做了一些挖掘,发现close()完全破坏了一个套接字并使其无法用于其余的运行(请纠正我,如果我错了。)

现在令我困惑的是:

a)我仍然可以使用套接字来接受,并且我找回文件描述符,问题是当我尝试在套接字上使用recv()时这样。

n = (recv(c->client[threadLocal], str, 100, 0); 

(错误检查在这里省略但我确实有)

b)当我到达我的套接字数组中的最后一个插槽时,我可以重复使用套接字,这很奇怪,如果第一次运行时遇到问题但不是最后一次我得到的感觉我很想念一些东西

c)如何使套接字可重用?或者什么是制作可以在程序运行的其余部分重复使用的套接字的好方法。

所有帮助都非常适合,因为老实说我对这里发生的事情感到很困惑。

编辑:好的,这是我尝试做的一个小例子。我在一个结构中有一个套接字数组,代表服务器上的插槽。我意识到可能更容易做一个代表包含套接字的玩家的结构列表,所以当有人加入时你可以创建一个新的结构,但我现在不想,因为这需要大量的工作,但是如果没有选择,我会这样做。

struct clientData{
 int clientSocket[maxplayers];
 //and some other stuff
};

当玩家加入时,他们会获取列表中的第一个可用套接字并接受(),当客户端断开连接时,我希望套接字可供其他客户端声明。基本上我希望旧客户端放弃close()或类似的东西以及稍后连接的新客户端,以便能够在阵列中重用此套接字/位置。

我正在寻找一种重置套接字的方法,以便在需要时再次使用它。 我希望这让事情变得更容易理解,再次感谢。

1 个答案:

答案 0 :(得分:5)

你混淆了两种不同类型的套接字。

有听音插座。调用listen时,将套接字置于侦听套接字中。然后,您可以在侦听套接字上调用accept以获取连接的套接字。如果您不想再监听新连接(至少不在该端口上),那么close监听套接字的唯一时间就是{。您永远不会在侦听套接字上拨打sendrecv,因为他们没有连接任何内容。

有连接套接字。当您在侦听套接字上呼叫accept时,您将获得一个全新的连接套接字。您可以在连接的套接字上呼叫sendrecv以与另一端通信。当您使用已连接的套接字时,应该close它。然后连接的套接字将被完全销毁。

您可以继续在侦听套接字上呼叫accept以获得更多已连接的套接字,因为您需要在这些连接的套接字上调用sendrecvclose这样做是为了管理你的各种联系。

您可能还会将插槽与插槽句柄混淆。有时人们会使用术语" socket"对彼此而言。但是有一个套接字本身,它是一个可能连接也可能没有连接的通信端点,然后是套接字句柄,它是一个用于引用特定套接字的数字。

您无法重用实际套接字 - 它是死连接的端点。您可以重新使用套接字句柄。一旦调用close,无论实际套接字发生什么,都可以重用句柄。您对socketaccept的下一次调用可能会返回相同的句柄。 (但不要假设它存在,只需存放手柄。)

  

当玩家加入时,他们会获取列表中的第一个可用套接字并接受(),当客户端断开连接时,我希望套接字可供其他客户端声明。基本上我希望旧客户端放弃close()或类似的东西以及稍后连接的新客户端,以便能够在阵列中重用此套接字/位置。

新客户端可以重用套接字句柄和数组中的位置。在侦听套接字上调用accept并将新连接的套接字句柄存储在空闲数组插槽中。

我假设你的第一句话措辞有点糟糕。我怀疑你的意思是这样的:" 对于一个玩家加入服务器,分配了一个数组中的插槽。线程在服务器的侦听套接字上调用accept,并将返回的套接字描述符存储在数组的该插槽中。"

当您完成连接后,close连接的套接字并将阵列中的插槽标记为空闲。然后,您可以在侦听套接字上再次调用accept,也许可以返回相同的套接字描述符,但无论哪种方式都将新连接的套接字存储在数组的该插槽中并处理新客户端。