前言:
select系统调用的用途是:在指定的一段时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。
select API:
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
FD_ZERO(fd_set *fd_set); //清除fdset的所有位
FD_SET(int fd, fd_set *fd_set); //设置fdset的位fd
FD_CLR(int fd, fd_set *fd_set): //清除fdset的位fd
int FD_ISSET(int fd, fd_set *fdset); //测试fdset的位fd是否被设置(文件描述符fd是否就绪)
文件描述符的就绪条件:
--可读
1、socket内核接收缓冲区中的字节数大于或等于其低水位标记SO_RCVLOWAT。此时我们可以无阻塞地读取该文件描述符,并且读操作返回的字节数大于0。
2、socket通信的对方关闭连接。此时对该socket的读操作将返回0。
3、socket上有未处理的错误。
--可写
1、socket内核发送缓冲区中的可用字节数大于或等于其低水位标记SO_SNDLOWAT,此时我们可以无阻塞地写该socket,并且写操作返回的字节数大于0。
2、socket的写操作被关闭。
3、socket使用非阻塞connect连接成功或者失败(超时)之后。
4、socket上有未处理的错误。
编码实例
服务端select_s.c
/*
*单进程IO多路复用select模型
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <unistd.h>
#include <sys/types.h>
#define IPADDRESS "127.0.0.1"
#define PORT 8787
#define MAXLINE 1024
#define LISTENQ 5
//创建套接字并进行绑定
static int socket_bind(const char* ip,int port);
//IO多路复用select
static void do_select(int listenfd);
//处理