关于select函数.docx

上传人:b****6 文档编号:7139245 上传时间:2023-01-21 格式:DOCX 页数:8 大小:16.53KB
下载 相关 举报
关于select函数.docx_第1页
第1页 / 共8页
关于select函数.docx_第2页
第2页 / 共8页
关于select函数.docx_第3页
第3页 / 共8页
关于select函数.docx_第4页
第4页 / 共8页
关于select函数.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

关于select函数.docx

《关于select函数.docx》由会员分享,可在线阅读,更多相关《关于select函数.docx(8页珍藏版)》请在冰豆网上搜索。

关于select函数.docx

关于select函数

关于select函数

关于select函数,其函数原型为:

intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtim*timeout);

此函数的功能是由内核检测在timeout时间内,是否有readfds,writefds,exceptfds三个句柄集(filedescriptors)里的某个句柄(filedescriptor)的状态符合寻求,即readfds句柄集里有句柄可读或writefds句柄集里有可写或exceptfds句柄集里有例外发生,任何一个有变化函数就立即返回,返回值为timeout发生状态变化的句柄个数。

n是所有readfds,writefds,exceptfds三个句柄集(filedescriptors)里编号最大值加1。

比如:

要检测两个socket句柄fd1和fd2在timeout时间内是否分别可读和可写就可以这样:

先把两个句柄集(filedescriptors)清零:

FD_ZERO(&readfds);

FD_ZERO(&writefds);

然后把fd1加入读检测集:

FD_SET(fd1,&readfds);

然后把fd2加入写检测集:

FD_SET(fd2,&writefds);

再给timeout设置值,timeout是这样的一个结构:

structtim{

longtv_sec;

longtv_usec;

};

你可以这样赋值:

timeout.tv_sec=1;

timeout.tv_uec=0;

表示检测在1秒钟内是否有句柄状态发生变化。

如果有句柄发生变化,就可以用FD_ISSET检测各个句柄,比如:

FD_ISSET(fd1,&readfds);//检测是否fd1变成可读的了

FD_ISSET(fd2,&writefds);//检测是否fd2变成可写的了

示意程序代码如下:

fd1=socket();//创建一个socket

fd2=socket();//创建一个socket

while

(1){

FD_ZERO(&readfds);

FD_ZERO(&writefds);

FD_SET(fd1,&readfds);

FD_SET(fd2,&writefds);

timeout.tv_sec=1;

timeout.tv_uec=0;

ret=select(fd1>fd2?

(fd1+1):

(fd2+1),&readfds,&writefds,NULL,&timeout);

if(ret<0){printf("系统错误,select出错,错误代码:

%d,错误信息:

%s",errno,strerror(errno));}

elseif(ret==0){printf("select超时返回,没有任何句柄状态发生变化!

");}

//有句柄状态发生了变化

if(FD_ISSET(fd1,&readfds)){

fd1有数据可读;

fd1里的数据被读出来;

}

if(FD_ISSET(fd2,&writefds)){

fd2可写;

fd2里发送数据给对方;

}

}经常用到的几个自定义函数:

1、开启监听的函数int

OpenSCPServer(intport,inttotal,intsendbuflen,intrecvbuflen,intblockORnot,intreuseORnot){intsockfd=0,ret=0,opt=0,flags=1;

structsockaddr_inladdr;

ret=sockfd=socket(PF_INET,SOCK_STREAM,0);

if(ret<0){

sprintf(errorMessage,"OpenTCPServersocket()error!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

return-1;

}

ret=setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuseORnot,sizeof(int));

if(ret<0){

sprintf(errorMessage,"OpenTCPServersetsockopt()reuseerror!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

return-2;

}

ret=setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&recvbuflen,sizeof(int));

if(ret<0){

sprintf(errorMessage,"OpenTCPServersetsockopt()recvbuferror!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

return-3;

}

ret=setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sendbuflen,sizeof(int));

if(ret<0){

sprintf(errorMessage,"OpenTCPServersetsockopt()sendbuferror!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

return-4;

}

ioctl(sockfd,FIONBIO,&blockORnot);

laddr.sin_family=PF_INET;

laddr.sin_port=htons(port);

laddr.sin_addr.s_addr=INADDR_ANY;

bzero(&(laddr.sin_zero),8);

ret=bind(sockfd,(structsockaddr*)&laddr,sizeof(structsockaddr));

if(ret<0){

sprintf(errorMessage,"OpenTCPServerbind()error!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

close(sockfd);

return-5;

}

ret=listen(sockfd,total);

if(ret<0){

sprintf(errorMessage,"OpenTCPServerlisten()error!

return:

%d,errno=%d,errortext:

'%s'%s",ret,errno,strerror(errno),GetCurrentTime(0,0));

close(sockfd);

return-6;

}

sprintf(errorMessage,"OpenTCPServeropenedonport.%d(%d)OK,socket(%d),buf(%d:

%d)!

%s",port,total,sockfd,sendbuflen,recvbuflen,GetCurrentTime(0,0));

returnsockfd;

}2、连接服务器的函数int

ConnectSCPServer(char*serverip,intserverport,intblockORnot){intserversock=0,ret=0;

unsignedlongaddr;

structsockaddr_insin;

structhostent*he;

if((he=gethostbyname(serverip))==0){

sprintf(errorMessage,"ConnectSCPServerIPaddress'%s'error!

return:

-1%s",serverip,GetCurrentTime(0,0));

return-1;

}

serversock=socket(PF_INET,SOCK_STREAM,0);

if(serversock==-1){

sprintf(errorMessage,"ConnectSCPServersocket()error!

return:

-2,errno=%d,errortext:

'%s'%s",errno,strerror(errno),GetCurrentTime(0,0));

return-2;

}

ioctl(serversock,FIONBIO,&blockORnot);//blockornot

memset((char*)&sin,0,sizeof(structsockaddr_in));

sin.sin_family=PF_INET;

sin.sin_port=htons(serverport);

sin.sin_addr=*((structin_addr*)he->h_addr);

ret=connect(serversock,(structsockaddr*)&sin,sizeof(sin));

if(ret==-1){

sprintf(errorMessage,"ConnectSCPServerconnect()error!

return:

-3,errno=%d,errortext:

'%s'%s",errno,strerror(errno),GetCurrentTime(0,0));

close(serversock);

return-3;

}

returnserversock;

}3、发送数据函数Sendint

Send(intsock,char*buf,size_tsize,intflag,inttimeout){inti=0,ret=0,intretry=0;

structtimtival;

fd_setwritefds;

intmaxfds=0;

tival.tv_sec=timeout;

tival.tv_usec=0;

FD_ZERO(&writefds);

if(sock>0){

FD_SET(sock,&writefds);

maxfds=((sock>maxfds)?

sock:

maxfds);

}

else{

sprintf(errorMessage,"Sendsocket:

%derror!

return:

-2%s",sock,GetCurrentTime(0,0));

return-2;

}

ret=select(maxfds+1,NULL,&writefds,NULL,&tival);

if(ret<=0){

if(ret<0)sprintf(errorMessage,"Sendsocket:

%dselect()error!

return:

%d,errno=%d,errortext:

'%s'%s",sock,ret,errno,strerror(errno),GetCurrentTime(0,0));

elsesprintf(errorMessage,"Sendsocket:

%dselecttimeout(%d)!

%s",sock,timeout,GetCurrentTime(0,0));

close(sock);

return-3;

}

if(!

(FD_ISSET(sock,&writefds))){

sprintf(errorMessage,"Sendsocket:

%dnotinwritefds!

%s",sock,GetCurrentTime(0,0));

close(sock);

return-4;

}

while(i<size){

ret=send(sock,buf+i,size-i,flag);

if(ret<=0){

sprintf(errorMessage,"Sendsocket:

%dsend()error!

return:

%d,errno=%d,errortext:

'%s'%s",sock,ret,errno,strerror(errno),GetCurrentTime(0,0));

if(EINTR==errno)

if(intretry<10){intretry++;continue;}

elsesprintf(errorMessage,"Sendsocket:

%dsend()error!

EINTR10times!

%s",sock,GetCurrentTime(0,0));

close(sock);

return-1;

}

elsei+=ret;

}

sprintf(errorMessage,"Sendsocket:

%dsend()OK!

%d/%dbytessent!

%s",sock,i,size,GetCurrentTime(0,0));

returni;

}4、接收数据函数Recvint

Recv(intsock,char*buf,size_tsize,intflag,inttimeout){inti=0,ret=0,intretry=0;

structtimtival;

fd_setreadfds;

intmaxfds=0;

tival.tv_sec=timeout;

tival.tv_usec=0;

FD_ZERO(&readfds);

if(sock>0){

FD_SET(sock,&readfds);

maxfds=((sock>maxfds)?

sock:

maxfds);

}

else{

sprintf(errorMessage,"Recvsocket:

%derror!

return:

-2%s",sock,GetCurrentTime(0,0));

return-2;

}

ret=select(maxfds+1,&readfds,NULL,NULL,&tival);

if(ret<=0){

if(ret<0)sprintf(errorMessage,"Recvsocket:

%dselect()error!

return:

%d,errno=%d,errortext:

'%s'%s",sock,ret,errno,strerror(errno),GetCurrentTime(0,0));

elsesprintf(errorMessage,"Recvsocket:

%dselecttimeout(%d)!

%s",sock,timeout,GetCurrentTime(0,0));

close(sock);

return-3;

}

if(!

(FD_ISSET(sock,&readfds))){

sprintf(errorMessage,"Recvsocket:

%dnotinreadfds!

%s",sock,GetCurrentTime(0,0));

close(sock);

return-4;

}

while(i<size){

ret=recv(sock,buf+i,size-i,flag);

if(ret<=0){

sprintf(errorMessage,"Recvsocket:

%drecv()error!

return:

%d,errno=%d,errortext:

'%s'%s",sock,ret,errno,strerror(errno),GetCurrentTime(0,0));

if(errno==EINTR)

if(intretry<10){intretry++;continue;}

elsesprintf(errorMessage,"Recvsocket:

%drecv()error!

EINTR10times!

%s",sock,GetCurrentTime(0,0));

close(sock);

return-1;

}

elsei+=ret;

}

sprintf(errorMessage,"Recvsocket:

%drecv()OK!

%d/%dbytesreceived!

%s",sock,i,size,GetCurrentTime(0,0));

returni;

}

最后需要说明的是:

我这里讲到的源程序并不能实际地作为一个产品程序来用,实际情况下可能会有其它许多工作要做,比如可能要建立共享队列来存放socket里读到的消息,也可能把发送消息先进行排队然后再调用Send函数。

还有,如果不是全数字,在发送前一定要htonl转换为网络字节序,同理接收到后一定要先ntohl由网络字节序转换为主机字节序,否则对方发送过来的0x00000001在你这里可能是0x00010000,因为高低位顺序不同。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1