Linux socket编程(二)之select()
seclet()监听指定文件描述符集中的成员是否发生读写或者异常的变化。函数原型如下:
int select(int maxfd,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
/*maxfd:集合中最大的文件描述符加1,是一个整数成员;
readfds:指向读文件描述符集结构的指针,如果select()监听到此文件描述符集有成员变化时就返回一个正数,意味着可以向这个成员读数据,如果没有 监测到有成员变化就等待第三个参数设置的时间后返回0表示等待超时,如果监测出错,返回-1;
writefds:指向写文件描述符集结构的指针,如果select()监听到此文件描述符集有成员变化时就返回一个正数,意味着可以向这个成员写数据,如果没 有监测到有成员变化就等待第三个参数设置的时间后返回0表示等待超时,如果监测出错,返回-1;
errorfds:功能同上;
timeout:指向struct timeval结构的指针,用于设置等待时间,如果参数设置为零不等待监测无变化立即返回,设置为NULL一直等待直到有变化,设置为 具体哪个数即设置等待的时间,时间过后还无变化,select()返回0,表示超时;
注意:读写文件描述符集均可设置为NULL,表示忽略其中的变化;*/
各成员如何赋值:
maxfd:C语言基本操作判断大小;
fd_set结构体指针:
1.声明
fd_set readfds;
fd_set writefds;
2.赋值fd_set集合可以通过一些宏函数人为操作,如清空集合 FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set *),将一个给定的文件描述符从集合中删除FD_CLR(int ,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* );
3.readfds和writefds在select()中做参数时通过“&”转化为指针;
timeout:对struct timeval的秒,毫秒成员赋值;
例程代码如下:
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/un.h>
#include<sys/time.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<netinet/in.h>
#define SERVERPORT 1234
#define BACKLOG 10
#define MAX_CNN_NUM 10
#define MAXDATASIZE 100
int main()
{
struct sockaddr_in server_sockaddr,client_sockaddr;
int sin_size,recvbytes;
fd_set readfd;
fd_set writefd;
int sockfd,client_fd;
char buf[MAXDATASIZE];
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
printf("socket success!,sockfd=%d\n",sockfd);
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(SERVERPORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(server_sockaddr.sin_zero),8);
if(bind(sockfd,(struct sockaddr*)&server_sockaddr,sizeof(struct sockaddr))==-1)
{
perror("bind");
exit(1);
}
printf("bind success!\n");
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen");
exit(1);
}
printf("listening.....\n");
FD_ZERO(&readfd);
FD_SET(sockfd,&readfd);
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if(select(MAX_CNN_NUM,&readfd,NULL,NULL,(struct timeval *)0)>0)
{
if(FD_ISSET(sockfd,&readfd)>0)
{
if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))==-1)
{
perror("recv");
exit(1);
}
if(read(client_fd,buf,MAX_CNN_NUM)<0)
{
perror("read");
exit(1);
}
printf("received a connection:%s",buf);
}
close(client_fd);
}
}
}
此例程只是服务器端例程,仅作为select()使用的参考!