TCP通信服務器端實現第三步:調用listen 網絡API,將套接字文件描述符,從主動變爲被動文件描述符【linux】(zzv)

listen函數

函數原型

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);

功能

將套接字文件描述符,從主動文件描述符變爲被動描述符,然後用於被動監聽客戶的連接。

返回值

成功返回0,失敗返回-1,ernno被設置

參數

sockfd

socket所返回的套接字文件描述符。
socket返回的“套接字文件描述符”默認是主動的,如果你想讓它變爲被動的話,你需要自己調用listen函數來實現。

backlog

指定隊列的容量。

這個隊列用於記錄正在連接,但是還沒有連接完成的客戶,一般將隊列容量指定爲2、3就可以了。

這個容量並沒有什麼統一個設定值,一般來說只要小於30即可。

代碼演示

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SPROT 5006
#define SIP "192.168.31.162"
void  print_err(char * str,int line,int err_no)//出錯處理函數
{
	printf("%d,%s: %s\n",line,str,strerror(err_no));
	exit(-1);
}
int main(void)
{
	int ret = -1;
	int sockfd = -1; //存放套接字文件描述符
	/*創建使用TCP協議通信的套接字文件*/
	sockfd =  socket(PF_INET,SOCK_STREAM,0); //指定TCP協議
	if(-1 == sockfd) //進行出錯處理
		print_err("socket fail",__LINE__,errno);

	/*調用bind函數綁定套接字文件/ip/端口*/
	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;//指定ip格式
	saddr.sin_port= htons(SPROT);//指定端口
	saddr.sin_addr.s_addr = inet_addr(SIP);//設置ip
	ret = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//綁定
	if(-1 ==ret)
		print_err("bind fail",__LINE__,errno);

	/*將主動的套接字文件描述符轉換爲被動的文件描述符,用於被動監聽客戶連接。*/
	ret = listen(sockfd,3);
	if(-1 ==ret)
		print_err("listen fail",__LINE__,errno);
	return 0;
}

實現被動監聽客戶端連接使用的是另外一個函數,listen函數本身並不會去監聽,只是把主動描述符轉化爲被動描述符,真正等待監聽的函數時另外的函數。

不要因爲listen有聽的意思,就想當然的認爲,listen就是用於被動監聽客戶連接的函數,事實上真正用於被動監聽客戶連接的函數,並不是listen,而是其它函數。

listen的作用僅僅只是用於將“套接字文件描述符”變成被動描述符,以供“監聽函數”用於被動監聽客戶連接而已。

TCP服務器爲什麼要listen

一定要注意 : 只有TCP服務器纔會調用listen

圖解說明:TCP編程模型
TCP編程模型

TCP服務器調用listen函數的目的。

TCP服務器監聽客戶連接時,是使用socket返回的“套接字文件描述符”來實現的,但是這個文件描述符默認是主動文件描述符,所以需要使用listen函數將其轉爲被動描述符,否者無法用於被動監聽客戶的連接。

什麼是主動描述符?
使用主動描述符可以主動的向對方發送數據。

什麼是被動描述符?
只能被動的等別人主動想你發數據,然後再回答數據,不能主動的發送數據。

爲什麼要將“套接字文件描述符”轉爲被動描述符後,才能監聽連接?
TCP服務器和客戶端必須要建立連接,建立連接時的三次握手是由客戶端主動先發起的,
也就是由客戶端率先主動向服務器發送三次握手的數據,而服務器這一端則被動的接收,然後回答。

圖解說明:

TCP通信模型

正是由於服務器在三次握手時的這一被動屬性,所以使用“套接字文件描述符”監聽客戶連接時,描述符必須是被動的描述符,否則服務器無法監聽被動連接。

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