精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
(言下之意,在底层缓冲里有数据时接收才是最优化,在底层缓冲有空间发送数据时发送才是最优化。如果在没有数据时,强行开始接收,要么是阻塞等待时间长,要么是过了等待时间有些数据就接收不到了)
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
int select(int n,fd_set *readfds,fd_set*writefds,fd_set*exceptfds,struct timeval *timeout); struct timeval { long tv_sec,long tv_usec };
FD_ZERO(fd_set*set); |
清除集内所有位 |
FD_CLR(int fd,fd_set *set); |
关闭fd对应的位 |
FD_SET(int fd,fd_set*set); |
开启fd对应的位 |
FD_ISSET(int fd,fd_set*set); |
检测fd对应的位是否设置上 |
示例
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/select.h>
int main (void) { fd_set fd_rset, fd_wset; struct timeval timeout; int rc; FD_ZERO (&fd_rset);//对描述符集清0 FD_ZERO (&fd_wset); /* Watch stdin for input, stdout for output. 监视标准输入和标准输出*/ FD_SET (0, &fd_rset);//相当于把0描述符加到fd_rset集里 FD_SET (1, &fd_wset); timeout.tv_sec = 3; timeout.tv_usec = 50000; rc = select (2, &fd_rset, &fd_wset, NULL, &timeout);//注意这里的2是上面0,1中间找最大值1加1的值,0代表输入,1代表输出 if (rc) { printf ("Data is available now.\n"); if (FD_ISSET (0, &fd_rset))//判断fd_rset集里0描述符位置设置上没有,设置上了就表示它有状态了 printf ("Data ready for reading on fd=0\n"); if (FD_ISSET (1, &fd_wset)) printf ("Data ready on writing on fd=1\n"); } else { printf ("No data found in 3.05 seconds.\n"); } printf (" I am exiting\n"); exit (0); }
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int pselect(int n,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,const struct timespec*timeout,const sigset_t*sigmask);
不使用struct timeal,使用了:
struct timespec { long tv_sec;/*seconds*/ long tv_nsec;/*nanoseconds纳秒*/ }
这个有纳秒的精度(这并不暗示你的系统能够正常解析这样的级别)
timeout参数不会被函数修改了。
sigmask参数能够用来设置临时的事件掩码(哪些信号会被阻塞),在pselect调用时这些信号会被阻塞。
#include <sys/poll.h>
int poll(struct pollfd*ufds,unsigned int nfds,int timeout);
struct pollfd { int fd;/*file descriptor文件描述符*/ short events;/*requested events请求事件*/ host revents;/*returned events返回事件*/ }
POLLIN:正常或普通级别的带内数据能被读取
POLLRDNORM:正常数据能被读取
POLLRDBAND:普通级别带内数据能被读取
POLLPRI:高级别带内数据能够读取
POLLOUT:正常数据能够写入
POLLWRNORM:正常数据能够写
POLLWRBAND:正常级别带内数据能够写
POLLMSG:非标准值
POLLERR:有错误发生
POLLHUP:socket已经挂起
POLLINVAL:无效的描述符
示例
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/poll.h>
int main (void) { struct pollfd ufds[2];//定义2个fd int timeout; int rc; /* Watch stdin for input, stdout for output.监听标准输入和标准输出 */ ufds[0].fd = 0; ufds[0].events = POLLIN;//初始化监听信号ufds[1].fd = 1; ufds[1].events = POLLOUT; timeout = 3050;//超时时间 rc = poll (ufds, 2, timeout); printf (" poll returns %d, ufds[0].revents = 0x%03x, ufds[1].revents = 0x%03x\n", rc, ufds[0].revents, ufds[1].revents); if (rc < 0) { printf ("An error occurred\n"); exit (EXIT_FAILURE); } if (rc == 0) { printf ("No data found in 3.05 seconds.\n"); exit (EXIT_SUCCESS); } printf ("Data is available now.\n"); if (ufds[0].revents & POLLIN)//用按位与操作来判断是否来了读取操作 printf ("Data ready for reading on fd=0\n"); if (ufds[1].revents & POLLOUT)//用按位与操作来判断是否来了写入操作 printf ("Data ready on writing on fd=1\n"); exit (EXIT_SUCCESS); }
sd=socket(…) … listen(…); … for(;;) { cd=accept(…); pid=fork(); if(pid==0) {/*子进程*/ close(sd);//只是减少计数,没有真正关闭服务器端socket handle_the_client(); close(cd); exit(0); } close(cd);//父进程也要调用减少计数,才会真正关闭 }
#include <pthread.h> sd=socket(…); … listen(…); … for(;;){ cd=accept(…); pthread_create(&thr[cd],NULL,handle_the_client,&Data[cd]); pthread_detach(&the[cd]); } …