C非阻塞UDP套接字

C非阻塞UDP套接字,c,sockets,udp,C,Sockets,Udp,我一直在四处寻找如何让客户端在不阻塞主循环的情况下接收来自服务器的请求,对此我深表歉意,如果有重复的,但我在网上找到的都是TCP版本,它们不适合我的用途(UDP) 现在服务器只是一个Echo服务器,所以我不在乎它是否阻塞 服务器创建如下 ServerInstance Init(ServerConfiguration c) { ServerInstance n; n.endpoint = socket(PF_INET, SOCK_DGRAM, 0); Exitif(n.endpoint

我一直在四处寻找如何让客户端在不阻塞主循环的情况下接收来自服务器的请求,对此我深表歉意,如果有重复的,但我在网上找到的都是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;
}

感谢您的阅读并祝您愉快

看来SDL事件无法与任意非SDL事件进行多路复用。相反,您可以创建一个辅助线程,该线程使用
select()
epoll()
或围绕这些线程的一些包装器。此线程将等待网络消息,读取并可能解析这些消息,然后使用
SDL\u PushEvent

套接字引用的网络连接协议将请求传递给主线程,该协议对套接字的非阻塞设置和使用方式没有影响。套接字接口与网络协议无关。您有两个选项。我希望看到代码1/将套接字模式设置为非阻塞,或2/使用选项调用套接字函数来指定非阻塞调用。。。但我看不到这两个。。。所以我投票决定关闭。@Seb在我提出这个问题后,我将套接字设置为非阻塞模式,但与poll或select相比,这是最优的吗?我读了它浪费了CPUcycles@Whiteclaws1/2/不。无论如何,调用
recv
是必要的,不是吗?你最终还是给他们打了电话,不是吗?循环通过后,为每个非阻塞套接字调用
recv
,使用
sleep(0)
强制进行上下文切换,让操作系统有机会将更多数据放入队列中并。。。没有浪费;)此外,
poll
select
并不是完全非阻塞的,您还没有向我们展示该代码!在这个问题上没有什么是非阻塞的!不,我不想将事件推送到SDL队列,而是想找到一种以非阻塞方式轮询事件的方法-就像SDL对SDL_PollEvent所做的那样,网络上有没有关于如何使用轮询或选择来实现这一点的示例?如果可能的话,没有多线程,基本上,我想调用recv,如果没有等待处理的数据包,我会立即返回read@Whiteclaws:您可以找到数千个关于如何在套接字上使用select()进行IO多路复用的示例,但接下来您将如何检查SDL事件?如果您确实需要检查SDL事件和套接字事件,您可能实际上需要执行活动轮询或忙等待:检查套接字中的数据,检查SDL队列中的事件,睡眠一段时间,然后重复。此进程效率低下,但允许使用单个线程。
select
epoll
都不是唯一非阻塞的;根据“…
select()
阻塞,直到指定的超时间隔,直到至少一个指定的文件描述符的指定条件为真”,后者是异步I/O(与非阻塞I/O不同)。
  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);
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(...)
}