我正在使用Linux套接字在C ++中编写客户端 - 服务器对。我希望服务器监听连接,当连接一个客户端时,服务器应拒绝任何其他尝试连接的客户端。
我尝试通过将listen函数中的backlog参数设置为0并将其设置为1来实现此功能,并且这些值中的任何一个似乎都不起作用。第一个客户端按预期连接,但任何后续客户端只在第一个客户端完成时阻塞。对我来说真正令人困惑的是,他们不会阻止连接到服务器,他们会在第一次阅读时阻止。
我使用the code here开始编写我的客户端和服务器。有谁知道我需要更改以使服务器只接受一个客户端连接,并删除任何后续连接尝试?
答案 0 :(得分:7)
接受连接时,会创建一个新套接字。旧的仍旧用于监听未来的连接。
由于您希望一次只允许1个连接,因此您可以接受连接,然后在检测到您正在处理其他套接字时关闭新接受的套接字。
与接受之后关闭新接受的套接字相比,您是否存在净差异?客户端会在尝试使用其套接字时立即知道(如果已经在服务器上等待读取调用,则立即知道),最后一个错误是:服务器主动关闭连接。
答案 1 :(得分:4)
fork()
之后不要accept()
。
这个伪C代码只会同时接受一个客户端。
while(1) {
listen()
accept()
*do something with the connection*
close()
}
答案 2 :(得分:4)
您可以在接受第一个连接后关闭正在侦听连接的原始套接字。我不知道你使用的套接字类是否允许你这样做。
答案 3 :(得分:3)
听起来你需要手动实现它。让客户端连接,然后如果已经连接了另一个客户端,则从服务器向客户端发送断开连接消息。如果客户端收到此消息,请让它自行断开连接。
答案 4 :(得分:1)
由于您希望一次只允许1个连接,因此您可以接受连接,然后在检测到您正在处理其他套接字时关闭新接受的套接字。
我认为它应该是要关闭的侦听套接字。 建立第一个连接后,关闭原始侦听套接字。 之后不再建立联系。
第一次连接结束后,您可以创建一个新的套接字再次收听。
答案 5 :(得分:0)
如果您可以控制客户端,则可以使套接字无阻塞。在这种情况下,他们将返回错误消息EINPROGRESS
。
我仍在寻找如何将套接字更改为非阻塞。如果有人知道如何随意,请随时编辑答案。
答案 6 :(得分:0)
让接听套接字在接受并开始新连接后死亡。然后,当连接完成后,让它关闭一个新的侦听套接字。
答案 7 :(得分:0)
您可能在侦听套接字上设置了套接字选项TCP_DEFER_ACCEPT
:
TCP_DEFER_ACCEPT (since Linux 2.4) Allows a listener to be awakened only when data arrives on the socket. Takes an integer value (seconds), this can bound the maximum number of attempts TCP will make to complete the connection. This option should not be used in code intended to be portable.
我认为这会导致您所描述的效果,即连接客户端不会阻止connect
,而是阻止后续read
。我不确定选项默认设置是什么以及应该设置什么来禁用此行为,但是值为零可能值得一试:
int opt = 0;
setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &opt, sizeof(opt));
答案 8 :(得分:0)
据我所知,不可能只听一个连接。
Tcp涉及3次握手。在收到第一个syn
数据包之后,内核会将其与#34;连接"在等待队列中,使用syn/ack
回答并等待最终ack
。收到此消息后,它会将连接从等待队列移动到接受队列,应用程序可以使用accept()
调用来接收该连接。 (有关详细信息,请查看here。)
在linux上,backlog参数仅限制接受队列的大小。但是内核仍然会进行3次握手魔术。客户端接收syn / ack并用最终的ack回答并调用已建立的连接。
您唯一的选择是,在您接受第一个连接后立即关闭侦听套接字。 (但这可能导致其他连接已经可用。)或者您主动接受其他连接并立即关闭它们以通知客户端。
您拥有的最后一个选项是您正在使用的选项:让服务器对您的连接进行排队并一个接一个地处理它们。在这种情况下,您的客户将会阻止。