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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章