Socket中listen/accept函数的区别

listen函数

摘要:listen函数使用主动连接套接口变为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。

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

intlisten(int sockfd, int backlog)

参数sockfd

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

参数backlog

这个参数涉及到一些网络的细节。进程处理一个一个连接请求的时候,可能还存在其它的连接请求。因为TCP连接是一个过程,所以可能存在一种半连接的状态,有时由于同时尝试连接的用户过多,使得服务器进程无法快速地完成连接请求。如果这个情况出现了,服务器进程希望内核如何处理呢?内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接,这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限。这个backlog告诉内核使用这个数值作为上限。

毫无疑问,服务器进程不能随便指定一个数值,内核有一个许可的范围。这个范围是实现相关的。很难有某种统一,一般这个值会小30以内。

accept函数

摘要:accept()用来接受参数s的socket连接,它的函数原型是:

intaccept(int s,struct sockaddr * addr,int * addrlen)

服务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回 INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结构的长度。


listen只是把套接字从主动变为被动,并限制链接数;剩下的问题就是accept的,它会检测的;
listen意思是监听:但是它不是一直在监听,accept才是;

理解:listen函数不会阻塞,它只是相当于把socket的属性更改为被动连接,可以接收其他进程的连接。listen侦听的过程并不是一直阻塞,直到有客户端请求连接才会返回,它只是设置好socket的属性之后就会返回。监听的过程实质由操作系统完成。但是accept会阻塞(也可以设置为非阻塞),如果listen的套接字对应的连接请求队列为空(没有客户端连接请求),它会一直阻塞等待。


你可能感兴趣的:(linux网络编程)