C - 使用select()时如何限制服务器中的入站连接数

时间:2012-07-08 21:54:57

标签: c sockets tcp

我还是C socket编程的新手,但我能够创建一些简单的客户端和服务器程序。 我正在编写一个侦听TCP连接的服务器,其职责是回应客户端的请求,然后在客户端发送特殊字节序列时(或当它断开连接时)关闭通信。

我开始在无限循环内使用accept()函数对服务器进行编码:服务器等待客户端,接受()它,做所有的事情,close()是套接字描述符在结束并再次回去等待接受新客户。

由于我想一次为一个客户端服务,所以我以这种方式调用了listen函数:listen(mysocket, 1);

一切都很顺利,但随后出现了一个新问题。上面解释的服务器部分在一个单独的线程中运行(让我们称之为线程#2),主线程(线程#1)必须能够告诉它终止。我创建了一个全局变量,如果此变量设置为1(通过线程#1),则线程#2必须终止。问题是线程#2在调用accept()函数时卡住了,因此无法定期检查全局变量。

我显然需要该函数的超时值:“如果没有要接受的连接,请检查全局变量的值,如果设置为0则继续等待新连接,如果设置为1则继续等待。” / p>

我搜索了一个解决方案然后发现select()函数可以完成我需要的工作。虽然有点不同,但我第一次发现了fd_set和所有FD_ *宏。我修改了服务器部分以使其与select()函数一起工作,一切都很好,但是这里出现了最后一个问题,即我无法解决的问题。 如果以这种方式调用listen函数:listen(socket, 1);但服务器仍然同时接受并提供多个连接。这是因为select()适用于fd_set吗?我正在使用我在Web上找到的一些示例,当接受连接时,它会创建一个新的套接字描述符,该描述符与所有其他的一起进入集合。 我想接受只有一个客户端的连接,我写了一个简单的代码来识别是否应该提供连接客户端,但是有没有办法断开服务器端的连接?我知道我必须使用close()函数来关闭套接字描述符,但是当使用select()我正在使用fd_set时,我真的不知道如何关闭它们。 或者,有没有办法限制集合中套接字描述符的数量?我找到了FD_SETSIZE宏,但我无法使其工作,我甚至不确定它是否解决了这个问题。

感谢您的时间!

3 个答案:

答案 0 :(得分:5)

listen()函数有一个backlog参数,用于确定在可能被拒绝之前有多少传入请求待处理。这是措辞谨慎,以便操作系统实现可以支持 more 而不是您在listen()调用中指定的内容。您可能无法控制积压连接的确切数量。

如果一次只能支持一个客户端,则接受第二个连接但是告诉新客户端此时连接不可用,然后关闭新连接。这样做的好处是,您有机会告诉客户端连接不可用的原因。

答案 1 :(得分:0)

您也可以将listen()套接字放在fd_set中。 (我不明白你的问题是否已经这样做了)如果select表明listen套接字是可读的,你可以在listen套接字上调用accept。接受只返回一个fd。您也可以将返回的fd放入fd_set中。线程或多或少与此正交。 (systemcalls是原子的),但你当然可以搞砸了。

listen的backlog参数或多或少不相关;它只是指定系统应该同时维护多少个胚胎套接字(连接构建使用资源,甚至在套接字变为可用之前,如listen返回新fd所示)一旦三次握手完成accept将返回fd,胚胎连接将作为新的套接字fd诞生。

getdtablesize()宏是旧时的余数。在现代实现中,它基于getrlimit()。

FD_SETSIZE的根本问题是fd_set必须是左值,以便可以分配它。所以它必须是固定的大小。 (它可能是结构中的一个数组)为了避免固定大小的结构,你可以使用poll()而不是select()(或使用多个较小的fd_sets; - )

答案 2 :(得分:-1)

如果您使用的是Windows API,则可以尝试使用关键部分。