linux网络编程中listen函数 backlog的含义

结论: backlog 是用来指定在TCP连接时,同时进行 3次握手建立连接的客户端数量

listen函数在一般在调用bind之后-调用accept之前调用,
它的函数原型是:

#include
int listen(int sockfd, int backlog)
返回:0──成功, -1──失败

参数sockfd

被listen函数作用的套接字,sockfd之前由socket函数返回。在被socket函数返回的套接字fd之时,它是一个主动连接的套接字,也就是此时系统假设用户会对这个套接字调用connect函数,期待它主动与其它进程连接,然后在服务器编程中,用户希望这个套接字可以接受外来的连接请求,也就是被动等待用户来连接。由于系统默认时认为一个套接字是主动连接的,所以需要通过某种方式来告诉系统,用户进程通过系统调用listen来完成这件事。

参数backlog

这个参数涉及到一些网络的细节。在进程正理一个一个连接请求的时候,可能还存在其它的连接请求。因为TCP连接是一个过程,所以可能存在一种半连接的状态,有时由于同时尝试连接的用户过多,使得服务器进程无法快速地完成连接请求。如果这个情况出现了,服务器进程希望内核如何处理呢?内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接,这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限。这个backlog告诉内核使用这个数值作为上限。
毫无疑问,服务器进程不能随便指定一个数值,内核有一个许可的范围。这个范围是实现相关的。很难有某种统一,一般这个值会小30以内。
当调用listen之后,服务器进程就可以调用accept来接受一个外来的请求。关于accept更的信息,请接着关注本系统文章。

下面是来自于(http://blog.csdn.net/forrest_chen/article/details/7021409)的一段话:

TCP的
服务器端socket基本流程:
socket->bind->listen->accept->send/recv->closesocket,
客户端基本流程:
socket->[bind->]->connect->send/recv->closesocket,
其中客户端connect函数应该是和服务器端的listen函数相互作用,而不是accept函数。
在listen函数中的第二个参数backlog代表着等待处理的连接队列(以下简称队列)的长度,神马意思?我也不太懂,但是通过代码实践,我可以简单的说,每当有一个客户端connect了,listen的队列中就加入一个连接,每当服务器端accept了,就从listen的队列中取出一个连接,转成一个专门用来传输数据的socket(accept函数的返回值),所以在服务器端程序中有两个socket,前者是用来接收客户端连接的socket…

TCP的服务器端socket基本流程socket->bind->listen->accept->send/recv->closesocket,客户端基本流程socket->[bind->]->connect->send/recv->closesocket,其中客户端connect函数应该是和服务器端的listen函数相互作用,而不是accept函数。在listen函数中的第二个参数backlog代表着等待处理的连接队列(以下简称队列)的长度,神马意思?我也不太懂,但是通过代码实践,我可以简单的说,每当有一个客户端connect了,listen的队列中就加入一个连接,每当服务器端accept了,就从listen的队列中取出一个连接,转成一个专门用来传输数据的socket(accept函数的返回值),所以在服务器端程序中有两个socket,前者是用来接收客户端连接的socket…到这儿我就不太明白了,这似乎不像插座喔,用插座怎么描述这个过程…

拿经典情形来说,设置backlog值为1,那么能够往队列中塞的连接的数量为1,也就是服务器端能够接受的连接数为1,如果一个服务器端程序只有listen函数没有执行accept,那么会发现只有一个客户端能够进行连接,但由于服务器端没有accept,所以listen的队列中的连接就不能被取出了。但是如果有accept函数就不一样了,在服务器端是单线程情况下,listen一旦得到一个连接,加入队列之后就马上被accept函数取走了,然后又能有一个客户端连上,这就出现了似乎有两个客户端能够同时连接服务器端的情形,如果第一个连接此时一直没能断开,listen队列中的那个唯一的连接就不能取出,队列长度为1,新的客户端就不能connect上服务器端。其后面发生的事情就是这样的了。

以下内容有误,感谢网友。帖子有点久了,总结一句话,backlog是accept阻塞队列的长度,即等待accept的socket的最大数量。

另外再加一句,当accept生成的那个专门的用来传输数据的socket没有被close(closesocket函数)掉之前,accept是不会释放那个socket的,也就是说在close之前,accept无法从listen的队列中取出一个新的连接转成传输专用的socket。因此在服务器端单线程情况下,accept只有1个,backlog值为1,1+1 = 2,也就是前段说到的能够有两个客户端能够同时连接服务器端。但是如果服务器端是多线程的,就可以存在多个accept,那么这个backlog值的作用也就不怎么明显了,因为大家都在疯狂地从队列中取出连接,listen队列总是不为满的。

总而言之,connect往listen队列填装连接,每一个accept操作都会从listen队列取连接转成socket,等待这个socket close掉之后再继续从listen队列中取连接,而listen队列长度就是listen函数的第二个参数–backlog。

http://veithen.io/2014/01/01/how-tcp-backlog-works-in-linux.html

你可能感兴趣的:(Linux)