【发布时间】:2017-05-21 01:05:06
【问题描述】:
我一直在四处寻找如何让客户端在不阻塞主循环的情况下接收来自服务器的请求,我很抱歉,如果那里有重复,但我在网上找到的只是 TCP 版本,它不不适合我的目的 (UDP)。
现在服务器只是一个 Echo 服务器,所以我不在乎它是否阻塞。
服务器创建如下
ServerInstance Init(ServerConfiguration c) {
ServerInstance n;
n.endpoint = socket(PF_INET, SOCK_DGRAM, 0);
Exitif(n.endpoint < 0, "Error opening endpoint socket");
setsockopt(n.endpoint, SOL_SOCKET, SO_REUSEADDR, (const void *) &c.trueval, sizeof(int));
setzero((char *) &n.servaddr, sizeof(n.servaddr));
n.servaddr.sin_family = AF_INET;
n.servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
n.servaddr.sin_port = htons(c.portno);
Exitif(bind(n.endpoint, (struct sockaddr *) &n.servaddr, sizeof(n.servaddr)) < 0,
"Error on binding socket to addr");
n.buf = calloc(c.buffersize, sizeof(char))
return n;
}
至于客户:
connection = socket(AF_INET, SOCK_DGRAM, 0);
IfThenExit(socket < 0, "Error initializing UDP socket\n");
setzero((char *) &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
IfThenExit(inet_aton(SRVADDR, &servaddr.sin_addr) == 0, "IPV4 Address Invalid\n");
CleanQueueAdd(&connection, Socket);
它像上面那样循环,我也有 SDL 的事件池,我想知道如何在不阻塞程序的情况下实现类似的东西
if(1) {
while(SDL_PollEvent(&e)) {
switch(e.type) {
case SDL_QUIT:
quit = 1;
break;
case SDL_KEYDOWN:
quit = 1;
break;
}
}
// Recv here blocks ...
// recv(...)
}
感谢您的阅读,祝您有愉快的一天
【问题讨论】:
-
套接字引用的网络连接使用的协议对您如何设置套接字非阻塞和使用它没有影响。套接字接口独立于网络协议。
-
您有两个选择。我希望看到 1/ 将套接字模式设置为非阻塞的代码,或者 2/ 使用选项调用套接字函数来指定非阻塞调用......但是我没有看到这两个......所以我投票关闭。
-
@Seb 我提出这个问题后将套接字设置为非阻塞模式,但与轮询或选择相比,这是最优的吗?我读到它浪费了 CPU 周期
-
@Whiteclaws 1/ What is premature optimisation? 2/ 不。无论如何,调用
recv是必要的,不是吗?无论如何,你最终都会打电话给他们,不是吗?循环完成后,为每个 非阻塞 套接字调用recv,使用sleep(0)强制进行上下文切换,让操作系统有机会将更多数据放入队列并... 不浪费 ;) 此外,poll和select并非完全非阻塞,并且您还没有向我们展示该代码! 这个问题没有任何非阻塞!