之前對listen、accpet函數理解誤區----《Linux高性能服務器編程》讀書筆記

    以前一直以爲TCP建立連接3次握手過程服務端是對應accept函數調用,看了《Linux高性能服務器編程》才發現以前理解有誤。服務端建立了監聽端口就可以接受客戶端連接。服務端調用listen函數來創建一個監聽隊列以存放待處理的客戶連接。其中第二個參數backlog表示內核監聽隊列最大長度,也就是完全連接狀態(established)的socket上限,實際上是backlog+1。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>


static bool stop = false;
// SIGTERM handler func
static void handle_term( int sig )
{
	stop = true;
}


int main( int argc, char* argv[] )
{
	signal( SIGTERM, handle_term );
	
	if( argc < 3 )
	{
		printf("usage: %s ip port [backlog]\n", argv[0]);
		return 1;
	}
	
	const char* ip = argv[1];
	int port = atoi(argv[2]);
	int backlog = 5;
	if( argc > 3)
	{
		backlog = atoi(argv[3]);
	}
	
	int fd_listen = socket( PF_INET, SOCK_STREAM, 0 );
	assert( fd_listen >= 0 );
	
	struct sockaddr_in svr_addr;
	bzero( &svr_addr, sizeof(svr_addr) );
	svr_addr.sin_family = AF_INET;
	inet_pton( AF_INET, ip, &svr_addr.sin_addr );
	svr_addr.sin_port = htons( port );
	
	int ret = bind( fd_listen, (struct sockaddr*)&svr_addr, sizeof(svr_addr) );
	assert( ret != -1 );
		
	ret = listen( fd_listen, backlog );
	assert( ret != -1 );
	printf(" server listening [%s:%d]\n", ip, port);
	
	while( !stop )
	{
		sleep( 1 );
	}
	
	close( fd_listen );
	
	return 0;
}

運行服務端:默認backlog爲5


開啓多個nc連接服務端:



nc大於6個後,後面的連接狀態就是SYN_RECV,說明最多建立backlog+1個完整連接。

accept函數只是從監聽隊列取出連接,不論連接處於何種狀態(ESTABLISHED,CLOSE_WAIT),更不關心任何網絡狀況的變化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章