欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

实例说明listen()函数第二个参数的意义与用法

发布时间:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的这篇文章主要介绍了 实例说明listen()函数第二个参数的意义与用法 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

我们先来看结果:

Client:

[cpp] view plain copy
  • #include <sys/socket.h>  
  • #include <stdio.h>  
  • #include <string.h>  
  • #include <netinet/in.h>  
  • #include <stdlib.h>  
  • #include <arpa/inet.h>  
  •   
  • int main(int argc,char** argv)  
  • {  
  •     int ret;  
  •     int sockfd = socket(AF_INET,SOCK_STREAM,0);  
  •     if (sockfd == -1)  
  •     {  
  •         printf("socket error\n");  
  •         return -1;  
  •     }  
  •   
  •     struct sockaddr_in serveraddr;  
  •     memset(&serveraddr,0,sizeof(serveraddr));  
  •     serveraddr.sin_family = AF_INET;  
  •     inet_aton(argv[1],&serveraddr.sin_addr);  
  •     serveraddr.sin_port = htons((unsigned short)(atoi(argv[2])));  
  •       
  •     ret = connect(sockfd,(const sockaddr*)&serveraddr,sizeof(serveraddr));  
  •     if (ret == -1)  
  •     {  
  •         printf("connect error,ret = %d\n",ret);  
  •         return -1;  
  •     }  
  •     
  •     for(;;)  
  •     {}  
  •     return 0;  
  • }  

  • Server: [cpp] view plain copy
  • #include <sys/socket.h>  
  • #include <stdio.h>  
  • #include <string.h>  
  • #include <netinet/in.h>  
  • #include <stdlib.h>  
  • #include <arpa/inet.h>  
  •   
  •   
  • int main(int argc,char** argv)  
  • {  
  •     int ret;  
  •     int listenfd = socket(AF_INET,SOCK_STREAM,0);  
  •     if (listenfd == -1)  
  •     {  
  •         printf("socket error\n");  
  •         return -1;  
  •     }  
  •   
  •     struct sockaddr_in serveraddr;  
  •     memset(&serveraddr,0,sizeof(serveraddr));  
  •     serveraddr.sin_family = AF_INET;  
  •     serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  •     serveraddr.sin_port = htons((unsigned short)(atoi(argv[1])));  
  •   
  •     ret = bind(listenfd,(const sockaddr*)&serveraddr,sizeof(serveraddr));  
  •     if (ret == -1)  
  •     {  
  •         printf("bind error,ret = %d\n",ret);  
  •         return -1;  
  •     }  
  •   
  •   <span style="WHITE-SPACE: pre"> </span>int backlog = atoi(argv[2]);  
  •     ret = listen(listenfd, backlog);  
  •     printf("backlog = %d,ret =%d\n",backlog,ret);  
  •     if (ret == -1)  
  •     {  
  •         printf("listen error,ret = %d\n",ret);  
  •         return -1;  
  •     }  
  •       
  •     for(;;)  
  •     {}  
  •     return 0;  
  • }  
  • server的代码中通过命令行的方式传入backlog的值,以便于我们通过修改backlog来观察不同的backlog对程序的影响.

    开启一个server与3个client.

    backlog = 1时:



    backlog = 2时:

    观察上图,server在19890端口监听,3个client发起TCP连接。在第一幅图中,对client而言,3个状态均为established.对server而言,2个连接状态为established,一个为syn_recv.第二幅图中,对server而言,3个链接的状态均为established。

    我们先来看一下TCP连接的状态转换



    再说回listen(int fd,int backlog)函数,内核会为一个监听套接字维护两个队列,当有TCP请求到来时,即3次握手中的syn分节发送来时,会在未完成队列中增加一项,3次握手完成时,未完成队列中的项就移动到已完成队列里,accept()函数会从已连接队列里取走已完成连接.

    这个backlog参数就是控制我们的已连接队列里等待accept()取走的连接的最大数目的.注意一点,backlog与这个已排队连接的最大数目未必是完全相等的,不同的系统的实现可能不同.比如backlog=1,系统允许的实际一排队数目可能为2.


    所以在上图中,对client而言,connect()返回,TCP的状态就转变为established。而对server而言,3次握手完成TCP状态才会转换为established。在图一中,由于backlog参数的限制,导致有一条连接并未完成3次握手,所以状态为syn_recv。

    总结

    以上是生活随笔为你收集整理的实例说明listen()函数第二个参数的意义与用法的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。