Select (Unix)

select是用于I/O多路转接的一个系统调用函数。

在C语言中,该系统调用在 sys/select.h 或 unistd.h 中声明,语法如下:

int select(int nfds, fd_set readfds, fd_set writefds, fd_set errorfds, struct timeval timeout);

为了维护fd_set类型的参数,会使用下面四个宏:FD_SET(), FD_CLR(), FD_ZERO() 和 FD_ISSET()。

返回值:这个函数将返回描述符集的个数, 如果超时返回为0,错误则返回-1。

man参看:
*select(2)
*poll(2)

select与epoll的区别
说明:以上无论epoll_create, fd_set都受限于系统中单个进程能够打开的文件句柄数。

示例
#include
#include
#include

#include
#include
#include
#include

#include
#include
#include
#include

#define PORT "9421"

/ function prototypes /
void die(const char*);

int main(int argc, char **argv)
{
int sockfd, new, maxfd, on = 1, nready, i;

struct addrinfo res0, res, hints;

char buffer[BUFSIZ];

fd_set master, readfds;

ssize_t nbytes;

(void)memset(&hints, '\0', sizeof(struct addrinfo));

hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;

if(-1 == (getaddrinfo(NULL, PORT, &hints, &res0)))
die("getaddrinfo()");

for(res = res0; res; res = res->ai_next)
{
if(-1 == (sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))
{
perror("socket()");
continue;
}

if(-1 == (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(int))))
{
perror("setsockopt()");
continue;
}

if(-1 == (bind(sockfd, res->ai_addr, res->ai_addrlen)))
{
perror("bind");
continue;
}

break;

}

if(-1 == sockfd)
exit(EXIT_FAILURE);

freeaddrinfo(res0);

if(-1 == (listen(sockfd, 32)))
die("listen()");

if(-1 == (fcntl(sockfd, F_SETFD, O_NONBLOCK)))
die("fcntl()");

FD_ZERO(&master);
FD_ZERO(&readfds);

FD_SET(sockfd, &master);

maxfd = sockfd;

while(1)
{
memcpy(&readfds, &master, sizeof(master));

(void)printf("running select()\n");

if(-1 == (nready = select(maxfd+1, &readfds, NULL, NULL, NULL)))
die("select()");

(void)printf("Number of ready descriptor: %d\n", nready);

for(i=0; i0; i++)
{
if(FD_ISSET(i, &readfds))
{
nready--;

if(i == sockfd)
{
(void)printf("Trying to accept() new connection(s)\n");

if(-1 == (new = accept(sockfd, NULL, NULL)))
{
if(EWOULDBLOCK != errno)
die("accept()");

break;
}

else
{

if(-1 == (fcntl(new, F_SETFD, O_NONBLOCK)))
die("fcntl()");

FD_SET(new, &master);

if(maxfd

参见
*Berkeley套接字
*轮询
*epoll
*kqueue
*IOCP

外部链接
*
*

评论 (0)

  • 还没有评论,来抢沙发吧。