阻塞函数
读:read,recv,recvfrom
写:write,send
其他:accept,connect
【1】
int stat(const char *restrict path, struct stat *restrict buf);
获取文件属性
判断文件类型:
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
【2】fcntl
通过该函数设置文件描述符的属性
int fcntl(int fd, int cmd, long arg);
int flag;
flag = fcntl(0, F_GETFL); // 1.获取该文件描述符的原属性
flag |= O_NONBLOCK; //2. 修改对应的文件描述符的值
fcntl(0, F_SETFL, flag); // 3. 写回去
【3】I/O多路复用。其基本思想是:
1. 先构造一张有关文件描述符的表(集合、数组);
2. 将你关心的文件描述符加入到这个表中;
3. 然后调用一个函数。 select / poll
4. 当这些文件描述符中的一个或多个已准备好进行I/O操作的时候
该函数才返回(阻塞)。
5. 判断是哪一个或哪些文件描述符产生了事件(IO操作);
6. 做对应的逻辑处理;
****select函数返回之后,会自动将除了产生事件的文件描述符以外的位全部清空;
任务:
我想检测是键盘事件(标准输入 文件描述如为0 ),
还是鼠标事件(文件描述符是/dev/input/mouse1);
【4】select
/* According to POSIX.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:select用于监测是哪个或哪些文件描述符产生事件;
参数:
nfds: 监测的最大文件描述个数
readfds: 读事件集合; //读
writefds: 写事件集合; //NULL表示不关心
exceptfds:异常事件集合;
timeout: 超时检测 1
如果不做超时检测:传 NULL
select返回值: <0 出错
>0 表示有事件产生;
如果设置了超时检测时间:&tv
select返回值:
<0 出错
>0 表示有事件产生;
==0 表示超时时间已到;1
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
void FD_CLR(int fd, fd_set *set); //将set集合中的fd清除掉
int FD_ISSET(int fd, fd_set *set); //判断fd是否存在于set集合中
void FD_SET(int fd, fd_set *set); //将fd加入到集合中
void FD_ZERO(fd_set *set); //清空集合
任务1:
在TCP服务器代码中,实现并发,服务器可以响应多个客户端的连接请求;
同时也能响应键盘输入;
服务器端的代码要关心2个文件描述符, 0 sockfd
任务2:
服务器端监听: 0 sockfd acceptfd
可以实现服务器端相应多个客户端的登录和数据接收;
注意:
首先先监听0和sockfd,
当有客户端连接之后,accept函数返回,产生acceptfd
1. 需要将acceptfd加入到集合当中;
2. 需要更新maxfd
3. 当某一个客户端退出之后,这个客户端的acceptfd就失效了,
需要关闭这个acceptfd;清空这个集合对应位(置0)
作业:在线聊天室 基于UDP的