关于select函数Word文档格式.docx
《关于select函数Word文档格式.docx》由会员分享,可在线阅读,更多相关《关于select函数Word文档格式.docx(8页珍藏版)》请在冰豆网上搜索。
longtv_usec;
};
你可以这样赋值:
timeout.tv_sec=1;
timeout.tv_uec=0;
表示检测在1秒钟内是否有句柄状态发生变化。
如果有句柄发生变化,就可以用FD_ISSET检测各个句柄,比如:
FD_ISSET(fd1,&
//检测是否fd1变成可读的了
FD_ISSET(fd2,&
//检测是否fd2变成可写的了
示意程序代码如下:
fd1=socket();
//创建一个socket
fd2=socket();
while
(1){
ret=select(fd1&
gt;
fd2?
(fd1+1):
(fd2+1),&
readfds,&
writefds,NULL,&
timeout);
if(ret&
lt;
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);
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));
OpenTCPServersetsockopt()reuseerror!
return-2;
ret=setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&
recvbuflen,sizeof(int));
if(ret&
OpenTCPServersetsockopt()recvbuferror!
return-3;
ret=setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&
sendbuflen,sizeof(int));
if(ret&
OpenTCPServersetsockopt()sendbuferror!
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));
OpenTCPServerbind()error!
close(sockfd);
return-5;
ret=listen(sockfd,total);
OpenTCPServerlisten()error!
return-6;
OpenTCPServeropenedonport.%d(%d)OK,socket(%d),buf(%d:
%d)!
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){
ConnectSCPServerIPaddress'
error!
-1%s"
serverip,GetCurrentTime(0,0));
serversock=socket(PF_INET,SOCK_STREAM,0);
if(serversock==-1){
ConnectSCPServersocket()error!
-2,errno=%d,errortext:
errno,strerror(errno),GetCurrentTime(0,0));
ioctl(serversock,FIONBIO,&
//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){
ConnectSCPServerconnect()error!
-3,errno=%d,errortext:
close(serversock);
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(&
if(sock&
FD_SET(sock,&
maxfds=((sock&
maxfds)?
sock:
maxfds);
else{
Sendsocket:
%derror!
-2%s"
sock,GetCurrentTime(0,0));
ret=select(maxfds+1,NULL,&
tival);
=0){
0)sprintf(errorMessage,"
%dselect()error!
sock,ret,errno,strerror(errno),GetCurrentTime(0,0));
elsesprintf(errorMessage,"
%dselecttimeout(%d)!
sock,timeout,GetCurrentTime(0,0));
close(sock);
if(!
(FD_ISSET(sock,&
writefds))){
%dnotinwritefds!
while(i&
size){
ret=send(sock,buf+i,size-i,flag);
%dsend()error!
if(EINTR==errno)
if(intretry&
10){intretry++;
continue;
EINTR10times!
elsei+=ret;
%dsend()OK!
%d/%dbytessent!
sock,i,size,GetCurrentTime(0,0));
returni;
}4、接收数据函数Recvint
Recv(intsock,char*buf,size_tsize,intflag,inttimeout){inti=0,ret=0,intretry=0;
fd_setreadfds;
Recvsocket:
ret=select(maxfds+1,&
readfds,NULL,NULL,&
readfds))){
%dnotinreadfds!
ret=recv(sock,buf+i,size-i,flag);
=0){
%drecv()error!
if(errno==EINTR)
EINTR10times!
%drecv()OK!
%d/%dbytesreceived!
最后需要说明的是:
我这里讲到的源程序并不能实际地作为一个产品程序来用,实际情况下可能会有其它许多工作要做,比如可能要建立共享队列来存放socket里读到的消息,也可能把发送消息先进行排队然后再调用Send函数。
还有,如果不是全数字,在发送前一定要htonl转换为网络字节序,同理接收到后一定要先ntohl由网络字节序转换为主机字节序,否则对方发送过来的0x00000001在你这里可能是0x00010000,因为高低位顺序不同。