一、函数原型
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;
}