精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
(言下之意,在底层缓冲里有数据时接收才是最优化,在底层缓冲有空间发送数据时发送才是最优化。如果在没有数据时,强行开始接收,要么是阻塞等待时间长,要么是过了等待时间有些数据就接收不到了)
#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]);
}
…