读书人

关于unix网络编程select函数总是返回0

发布时间: 2012-04-22 18:34:46 作者: rapoo

关于unix网络编程select函数总是返回0的问题
服务器端:
int StartListen(sLsnPort)
char *sLsnPort;
{
struct sockaddr_in ServiceAddr;
struct sockaddr_in ClientAddr;
int nLsnSock = 0;
int nAcceptSock = 0;
int nPid = 0;
int status = 0;
int nReady = 0;
unsigned int nAddrlen = 0;
char sRecvBuffer[500],sSendBuffer[500];
fd_set socks;
struct timeval recvtime;

int n1 = 0,n2 = 0;


/*创建套接字*/
if((nLsnSock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("Create socket error:%s\r\n",strerror(errno));
return -1;
}
bzero(&ServiceAddr,sizeof(ServiceAddr));
ServiceAddr.sin_family = AF_INET;
ServiceAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

ServiceAddr.sin_port = htons(atoi(sLsnPort)); /*输入的端口号*/
/*绑定套接字*/
if(bind(nLsnSock,(struct sockaddr *)&ServiceAddr,sizeof(ServiceAddr)) < 0)
{
printf("Bind socket error:%s\r\n",strerror(errno));
return -1;
}
/*监听套接字*/
if(listen(nLsnSock,MAX_THREAD) != 0)
{
printf("Listen socket error:%s\r\n",strerror(errno));
close(nLsnSock);
return -1;
}
/*设置阻塞时间*/
recvtime.tv_sec = 15; /*阻塞时间为15秒*/
recvtime.tv_usec = 0;

/*循环监听F5请求*/
while(1)
{
n1++;
n2++;
printf("n1 = %d\r\n",n1);
memset(sRecvBuffer,0,500);
memset(sSendBuffer,0,500);
/* 检查是否有僵死进程 */
while(1)
{
nPid = wait3(&status, WNOHANG|WUNTRACED, NULL);
if(nPid > 0)
{
kill(SIGTERM, nPid);
}
else
{
break;
}
}
FD_ZERO(&socks); /*清空套接字描述符集*/
FD_SET(nLsnSock,&socks); /*在文件描述符集socks中增加一个新的文件描述符nLsnSock*/

nReady = select(nLsnSock+1,&socks,NULL,NULL,&recvtime); /*阻塞*/
if(nReady <=0 )
{
printf("select socket error:%d\r\n",nReady);
continue;
}
printf("n2 = %d\r\n",n2);
if(FD_ISSET(nLsnSock,&socks))
{
nAddrlen =sizeof(ClientAddr);
nAcceptSock = accept(nLsnSock,(struct sockaddr *)&ClientAddr,&nAddrlen);
if(nAcceptSock == -1)
{
printf("accept socket failed!\r\n");
continue;
}
read(nAcceptSock,sRecvBuffer,500);
printf("Recv :%s\r\n",sRecvBuffer);
/*生成日志分析文件*/

/*日志文件处理,返回分析结果*/


/*向F5服务器反馈分析结果*/
strcpy(sSendBuffer,"receive successful!");
send(nAcceptSock,sSendBuffer,500,0);
}
}
return(0);
}



客户端:
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in ClientAddr;
int nConnectSock = 0;
int nread;
int n = 0;
char sSendBuffer[100];
char sRecvBuffer[100];
fd_set socks; /*套接字描述符集*/

if((nConnectSock = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
printf("Create socket error:%s\r\n",strerror(errno));
return -1;
}

bzero(&ClientAddr,sizeof(ClientAddr));
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = htons(1043);
inet_pton(AF_INET, "127.0.0.1", &ClientAddr.sin_addr);

if(connect(nConnectSock,(struct sockaddr *)&ClientAddr,sizeof(ClientAddr)) < 0)
{
printf("Connect socket error:%s\r\n",strerror(errno));
return -1;
}
while(1)
{
memset(sSendBuffer,0,500);
memset(sRecvBuffer,0,500);


FD_ZERO(&socks);
FD_SET(nConnectSock,&socks);
FD_SET(0,&socks);

select(nConnectSock+1,&socks,NULL,NULL,NULL);
if(FD_ISSET(nConnectSock,&socks))
{
nread = recv(nConnectSock,sRecvBuffer,500,0);
printf("Recv:%s\r\n",sRecvBuffer);
}
if(FD_ISSET(0,&socks))
{
nread = read(0,sSendBuffer,500);
send(nConnectSock,sSendBuffer,500,0);
}
}
return(0);
}



运行情况如下:
服务器端:
n2 = 1
Recv :hello

n1 = 2
select socket error:0
n1 = 3
select socket error:0
n1 = 4
select socket error:0


客户端:
hello
Recv:receive successful!
hi
hello too




问题:
服务器端第一次调用select函数能监听到客户端的请求,返回值大于0。当客户端从第二次开始发送信息时,服务器端select返回的值都是0,为什么?


[解决办法]
服务器端:
select(nLsnSock+1,&socks,NULL,NULL,&recvtime); /*阻塞*/

上边一句有问题,查手册,在接收连接后,就不是nLsnSock+1了
应该是nAcceptSock+1,自己想想为什么

一般得是这样
int maxSockID(最好全局的)
开始用maxSockID = nLsnSock;
然后select(maxSockID+1,&socks,NULL,NULL,&recvtime); /*阻塞*/

当有新的连接到来时
nAcceptSock = accept(nLsnSock,...)成功后
然后maxSockID = nAcceptSock;


[解决办法]
楼主,tcp连接在accept后返回那个描述才应该被用来被监听。

你直接监听socket返回的描述符是不对的。
[解决办法]

探讨
对于1楼:
已经按你说的去改了,可是问题仍然存在。
修改如下:
nMaxSock = nLsnSock;
/*循环监听F5请求*/
while(1)
{
。。。。。。。。
nReady = select(nMaxSock+1,&socks,NULL,NULL,&recvtime); /*阻塞*/
...........
nAcceptSock = accept(……

读书人网 >UNIXLINUX

热点推荐