社区首页 >问答首页 >如何在udp for linux中使用select api问如何在udp for linux中使用select apiENStack Overflow用户提问于 2014-03-07 21:35:37回答 2查看 294关注 0票数 0代码语言:javascript运行复制 int CreateSocket()
{
socklen_t len;
// Socket creation for UDP
acceptSocket=socket(AF_INET,SOCK_DGRAM,0);
if(acceptSocket==-1)
{
printf("Failure: socket creation is failed, failure code\n");
return 1;
}
else
{
printf("Socket started!\n");
}
memset(&addr, 0, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
rc=bind(acceptSocket,(struct sockaddr*)&addr,sizeof(addr));
if(rc== -1)
{
printf("Oh dear, something went wrong with bind()! %s\n", strerror(errno));
return 1;
}
else
{
printf("Socket an port %d \n",port);
}
while(rc!=-1)
{
fd_set master;
fd_set read_fds;
int retval;
FD_ZERO(&master);
FD_ZERO(&read_fds);
FD_SET(acceptSocket, &master);
FD_SET(acceptSocket, &read_fds);
retval =select(2, &master, NULL, NULL, NULL);
len = sizeof(client);
if(retval == -1)
{
printf("error\n");
}
else if(FD_ISSET (acceptSocket, &master))
{
rc=recvfrom(acceptSocket,buf, 256, 0, (struct sockaddr*) &client, &len);
if(rc==0)
{
printf("Server has no connection..\n");
break;
}
if(rc==-1)
{
printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
break;
}
XcpIp_RxCallback( (uint16) rc, (uint8*) buf, (uint16) port );
}
else
{
makeTimer("First Timer", &firstTimerID, 2, 2); //2ms
makeTimer("Second Timer", &secondTimerID, 10, 10); //10ms
makeTimer("Third Timer", &thirdTimerID, 100, 100); //100ms
}
}
close(acceptSocket);
return 0;
}上面是udp层通过ip地址和端口号从客户端接收数据的服务器代码。我使用select api通过端口检查是否有数据,然后接收数据,否则调用计时器函数。我想实现从客户端接收数据,并在收到数据后调用定时器。但是上面的代码并没有调用计时器任务。上面代码中的错误是什么??使用select api是否有效?
timerudpcsocketsselect关注问题分享EN回答 2推荐最新Stack Overflow用户发布于 2014-03-07 21:48:45
select()的第一个参数是1 +三个集合中编号最高的FD,因此应该是acceptSocket +1。
(我假设您的实际问题比上面的代码更复杂,因为您可以只执行一个阻塞的recvfrom()调用,而不使用select()。如果您想在单个线程中处理多个套接字,和/或在超时后唤醒阻塞调用,则需要使用select(),尽管有其他方法可以实现后者。)
收藏分享票数 0ENStack Overflow用户发布于 2014-03-07 22:05:03
调用带有timeout == NULL的select()的方式,它将被阻塞,直到master中的某个文件描述符有数据要读取为止。在您的示例中,如果master只包含acceptSocket,则您调用makeTimer()的else将永远无法访问。
做
代码语言:javascript运行复制struct timeval timeout;
timeout.tv_sec = 0l;
timeout.tv_usec = 0l;
retval = select( acceptSocket+1, master, NULL, NULL, &timeout );只检查而不阻塞
请注意,如果由于超时而返回,则select()返回0,否则返回的描述符集中包含的文件描述符的数量。所以你还必须改变你的状态:
代码语言:javascript运行复制else if(FD_ISSET (acceptSocket, &master))至
代码语言:javascript运行复制else if(retval > 0 && FD_ISSET (acceptSocket, &master))因为否则您也会在超时后调用recvfrom(),在这种情况下,它将阻塞
收藏分享票数 0EN页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持原文链接:https://stackoverflow.com/questions/22251581
复制相关文章