linux socket編程---accept

一、函數原型

DESCRIPTION:
 *   The accept function is used with connection-based socket types
 *   (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
 *   connection request on the queue of pending connections, creates a new
 *   connected socket with mostly the same properties as 'sockfd', and
 *   allocates a new socket descriptor for the socket, which is returned. The
 *   newly created socket is no longer in the listening state. The original
 *   socket 'sockfd' is unaffected by this call.  Per file descriptor flags
 *   are not inherited across an accept.
 * 
int accept(int sockfd, 
		   FAR struct sockaddr *addr,
		   FAR socklen_t *addrlen)

  TCP客戶端依次調用socket()、connect()之後就想TCP服務器發送了一個連接請求。TCP服務器監聽到這個請求之後,就會調用accept()函數取接收請求,這樣連接就建立好了。

二、使用順序

一圖勝千言:
在這裏插入圖片描述

  • 第一個參數爲服務器的socket描述字;
  • 第二個參數爲指向struct sockaddr *的指針,用於返回客戶端的協議地址
  • 第三個參數爲協議地址的長度。
  • 如果accpet成功,其返回值是由內核自動生成的一個全新的描述字,代表與返回客戶的TCP連接。

三、使用場景

  在服務器端,通常建立了端口監聽以後,就會通過調用accept阻塞等待client的連接,這裏與select配合使用,可以提高服務器線程的使用效率,比如服務器線程同時監聽多個端口(綁定了socket),那麼我們不能每個socket到調用accept來阻塞等待client,這樣服務器線程就大大弱化了。
  可以採用select監控多個socket,然後調用FD_ISSET來判斷是哪個socket有數據,這樣便能實現一個線程監聽多個socket;

四、舉個例子

#include <stdio.h>
#include <errno.h>
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h> 
 
int main()
{
		//int fds; 
		int ret;
		char buf[100];
		int timecount;
		int maxfd;
		
		//設置監聽讀集合
		fd_set rfds;
		//設置等待時間,0不等待,NULL一直等待
		struct timeval tv;
		//清空集合
		FD_ZERO(&rfds);
		//把監聽的fd加入到集合中,這裏假設存在多個socket
		int socket_fd1 = 1;
		int socket_fd2 = 2;
        FD_SET(socket_fd1, &rfds);
        FD_SET(socket_fd2, &rfds);
		maxfd = socket_fd2 + 1;
		timecount = 0;
		while(1)
		{
		    //設置等待時間
			tv.tv_sec = 10;
			tv.tv_usec = 0;
			ret = select(maxfd, &rfds, NULL, NULL, &tv);
			if(ret<0)
			{
				printf("select error, process will eixt\n");
				exit(0);
			}
			//測試是否有數據
			else if(FD_ISSET(socket_fd1, &rfds))
			{
				int accept_fd = accept(socket_fd1, (struct sockaddr *)&clientaddr, &addrlen);
				.....
			}
			//測試是否有數據
			else if(FD_ISSET(socket_fd2, &rfds))
			{
				int accept_fd = accept(socket_fd2, (struct sockaddr *)&clientaddr, &addrlen);
				.....
			}
			else
			{
			
				timecount++;
				printf("\ntime out: %d\n", timecount);
			
			}
		}
		return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章