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