生活随笔
收集整理的這篇文章主要介紹了
实例说明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()函数第二个参数的意义与用法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。