C++ Winsock2:如何使用listen';一次只允许一个客户端连接;在VC&x2B+;

C++ Winsock2:如何使用listen';一次只允许一个客户端连接;在VC&x2B+;,c++,visual-c++,winsock,winsock2,C++,Visual C++,Winsock,Winsock2,我希望一次只允许从我的TCP服务器进行一个连接。你能告诉我,如何使用无积压长度为零的监听 我正在使用代码(如下所示),但当我逐个启动2个客户机时,两者都会连接起来。我正在使用VC++和winsock2 监听(m_插座,-1) 作为积压工作传递零也不起作用 等待你的答复 问候, immi您可以将backlog设置为1,因为这是您想要的连接数 但AFAIK对队列大小没有硬性保证(比如说,在BSD上会有1.5*backlog) 嗯,你最好手动控制连接的数量,在一定限制之后不要接受()连接。我想说,只接

我希望一次只允许从我的TCP服务器进行一个连接。你能告诉我,如何使用无积压长度为零的监听

我正在使用代码(如下所示),但当我逐个启动2个客户机时,两者都会连接起来。我正在使用VC++和winsock2

监听(m_插座,-1)

作为积压工作传递零也不起作用

等待你的答复

问候,

immi

您可以将backlog设置为1,因为这是您想要的连接数

但AFAIK对队列大小没有硬性保证(比如说,在BSD上会有1.5*backlog)


嗯,你最好手动控制连接的数量,在一定限制之后不要接受()连接。

我想说,只接受
一次。如果在服务器上一次只需要一个客户机,那么也只能使用一个线程来执行处理。backlog仅限制系统为接受而处理的挂起连接的数量(队列在第一次接受后再次为空,因此下一个客户端进入backlog),而不是连接的数量

这不是listen backlog的目的

侦听积压会影响用于挂起连接的队列,它允许TCP堆栈将挂起的连接排入队列,供您接受

要执行您想要执行的操作,您需要接受您允许的一个连接,然后关闭侦听套接字。完成单个客户端后,您可以重新创建侦听套接字并侦听新连接。这将阻止多个客户端连接到您,但客户端无法知道您实际上在“一次一个”的基础上运行和接受连接。所有的客户,除了一个成功连接的客户,都会认为你不在那里


保持监听套接字打开并接受所有连接可能是一种更好的设计,但一旦您有了“一个”活动连接,您只需接受,然后向您的客户端发送一条应用程序级消息,告诉它您不能接受更多的连接,或者如果无法接受,只需关闭新连接

如果确实可以将应用程序限制为仅使用Winsock 2,则可以使用其条件接受机制:

SOCKET sd = socket(...);
listen(sd, ...);
DWORD nTrue = 1;
setsockopt(sd, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char*)&nTrue, sizeof(nTrue));
这将改变堆栈的行为,只要连接积压空间可用,就不会自动向传入的SYN数据包发送回复。相反,您的程序会收到一个信号,表明它应该正常接受连接--select()、WSAEventSelect()、WSAAsyncSelect()…--然后调用wsaaaccept()而不是accept():

编写函数ConditionalAcceptChecker()以查看传入的连接信息并决定是否接受连接。在您的情况下,只要您已经在处理连接,就可以返回
CF\u REJECT


再次注意,此机制是Winsock 2特有的。如果您需要便携行为,其他帖子建议在您的程序已经连接时关闭监听插座更好。

elder_george,非常感谢您回答这个问题。但是,客户机连接请求在尝试连接tcp服务器时是否会失败。感谢您提供的建议。我明白你的意思了。它既好又实用。我不在乎,我将能够去接近关闭监听插座,但打算认真考虑第二种方法。我只是想问一下,有没有办法在听之前把插座带到这个状态?例如,如果我绑定了一个套接字,并且当前正在侦听它,那么如何在不关闭它的情况下取消该套接字上的侦听模式。等待你的答复。据我所知,没有办法。不管怎样,为什么要麻烦呢?这是一个很好的回答,沃伦·杨。感谢您的时间和回复。很好,我已经忘记了:)如果服务器拒绝连接,客户端会看到什么?在TCP级别重新启动,在Winsock级别重新启动WSAECONN。Warren Young,因为您的回答表明了我想做什么,我接受它。再次感谢您和所有回复的人,特别是Len Holgate,他给出了一些非常好的建议。我向你们所有人致以最良好的祝愿。
sockaddr_in sin;
WSAAccept(sd, (sockaddr*)&sin, sizeof(sin), ConditionalAcceptChecker, 0);