如何在udp for linux中使用select api

勤策365 admin 2025-09-14 05:22:10

社区首页 >问答首页 >如何在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

复制相关文章