select()函数经典错误
最近调试一个板载WiFi模块,需要进行UDP通信,怎么调试都会出现 ***select fail:Invalid argument*** 这样的错误,查看代码又感觉没有什么问题,然后注意调试,最终发现,是 *struct timeval timeout;//定义slect超时结构体* 未进行初始化造成的。 由于函数 int select(int nfds, fd_set* readset, fd_set* writeset, fe_set* exceptset, struct timeval* timeout) 需要调用到 struct timeval* timeou结构体,在函数内定义的该结构体,局部变量未初始化,导致timeou内时间随机,因此select报错,程序如下。
/**************************************************************************
* 函数名称: int udp_set_rcv( int sfd, const struct sockaddr *toAddr,fd_set *fds)
* 功能描述: 非阻塞接收recvfrom udp参数接口 用于板载WiFi发送set设置数据用
* 输入参数: sfd:创建socket的udp通道值 toAddr:发送到的socket结构体 ,fds 文件描述符集合
* 输出参数:
* 返 回 值: iResult 成功返回发送的参数指令的长度,失败返回-1 ,具体错误查看errno , 超时返回-2,说明没有参数返回,或者无通信
* 其它说明:
* 修改日期 版本号 修改人 修改内容
* -----------------------------------------------
* 2022/03/02 V1.0 ZhaoChengJie first commit
* 2022/03/03 V1.1 ZhaoChengJie add memset(&timeout, 0,sizeof(timeout)); 函数,缺少该函数导致select()报错,经典错误
**************************************************************************/
int udp_set_rcv( int sfd, const struct sockaddr *toAddr )
{
struct sockaddr_in *pT_RcvAddr = (struct sockaddr_in *)toAddr ;
int iResult=0;
int iRcvAddrLen = 0 ;
int iWatchDogTime = 0;
char cMsg[1024] = {0};
struct timeval timeout;//定义slect超时结构体
fd_set fds; //定义一个文件描述符集合
memset(&timeout, 0,sizeof(timeout)); //由于此处最开始未初始化,导致select()函数一直有问题!!!找了好久的bug!!!fuxk
iRcvAddrLen = sizeof( struct sockaddr_in ) ;
#if PRINTF_ALL_PARA
printf("sfd=%d\n", sfd );
#endif
//循环监视文件描述符集合
while(1)
{
iWatchDogTime ++ ;//看门狗
timeout.tv_sec = MAX_BLOCK_TIME;
#if PRINTF_ALL_PARA
printf("iWatchDogTime=%d--tv_sec=%d--usec=%d\n", iWatchDogTime, timeout.tv_sec, timeout.tv_usec);
#endif
if( iWatchDogTime > MAX_WATCHDOG_TIME )
{
printf("dead loop socket , communication failure\n" );
return -2;//通信未成功
}
FD_ZERO(&fds);//清空文件描述符集合
FD_SET( sfd, &fds); //把网络通信文件描述符加入到集合中
iResult = select(sfd+1,&fds,NULL,NULL,&timeout);//阻塞等待,直到集合中有活跃的描述符
#if PRINTF_ALL_PARA
printf(" iResult select = %d\n", iResult );
#endif
if(iResult < 0)//错误
{
perror(" select fail:");
//close(sfd);
return -1;
}
/*
else if(iResult == 0)//超时
{
perror("(nvram_set_SSID)select over time:");
close(sfd);
}
*/
else if(iResult > 0) //有活跃的 ret为1
{
#if PRINTF_ALL_PARA
printf(" rcv new data\n" );
#endif
if(FD_ISSET(sfd, &fds))//判断是否是new_socket_fd活跃,(有消息收到)
{
iResult = recvfrom(sfd, cMsg, sizeof(cMsg), 0, (struct sockaddr *)pT_RcvAddr, &iRcvAddrLen );//接收回来的信息和IP信息
if(iResult == -1)
{
printf(" RecvData result=%d--%s\n", iResult, strerror ( errno ) );
return iResult;
}
printf(" [%s:%d]",inet_ntoa(pT_RcvAddr->sin_addr),ntohs(pT_RcvAddr->sin_port));//打印消息发送方的ip与端口号
printf("msg=%s\n",cMsg );
return iResult;
}
}
memset(cMsg, 0, sizeof(cMsg));//清空存留消息
sleep(1);
}
}