【问题标题】:bidirectional socket (non-blocking) with c带 c 的双向套接字(非阻塞)
【发布时间】:2013-03-13 12:08:38
【问题描述】:

我尝试通过 TCP 套接字进行某种聊天。服务器端在 php 中实现并且(应该)可以正常工作。

没有,我在客户端遇到了问题(在 c [c99] 中实现):

我想从服务器监听(读取)“新字节”,并且每当用户输入新数据时,我也想向服务器发送(写入)“一些字节”。

现在的问题: -> 我如何监听传入流量(读取)并且仍然能够每 1 秒调用一次回调,我可以在其中检查新字节以发送到服务器? 我知道我必须使用 select(系统调用),但我不知道如何处理超时等。select 也会阻塞一段时间。

感谢您提供任何示例。

【问题讨论】:

  • 你考虑过使用线程吗?
  • 线程会以不好的方式解决问题。

标签: c sockets nonblocking


【解决方案1】:

有一个名为select 的函数可用于此目的。它可以检查套接字上是否有要读取的新输入,并且它具有超时,因此它也可以用于您的计时器。

它以一种或其他形式存在于所有主要操作系统上。只需在 Google 上搜索 socket select <your operating system> example,您就会得到大量结果。


select 的最后一个参数用于超时。它是一个指向 struct timeval 的指针,该结构包含用于设置超时的字段。

如果这个指针作为NULL 传递,则没有超时,select 可以无限期阻塞。

要设置超时,需要将timeval结构的tv_sec字段设置为秒数,tv_usec字段设置为微秒数(必须小于一百万)。通过将这些字段设置为零,您可以将超时设置为零,即快速轮询。

如果select 返回零,则存在超时。

例如,1.5 秒超时:

for (;;)
{
    fd_set readset;
    int maxfd;

    /* Initialize and set `readset` and `maxfd` */

    struct timeval tv;
    tv.tv_sec  = 1;
    tv.tv_usec = 500000;

    int res = select(maxfd + 1, &readset, NULL, NULL, &tv);

    if (res == -1)
        perror("select");  /* Error */
    else if (res == 0)
    {
        /* Timeout, do something */
    }
    else
    {
        /* A socket in `readset` is readable */
    }
}

如果select 返回超时之前,timeval 结构被修改以包含超时的剩余时间。

【讨论】:

  • 谢谢。我知道我必须使用选择。但是我如何设置超时?选择也块....任何想法的例子?我无法通过谷歌搜索找到 c 的示例。
  • 您还发现了一个损坏的链接!
  • @JonasSchnelli 由于您找到的链接不再有效,我已更新我的答案以包含更多文本和示例。
【解决方案2】:

使用 select system 调用。您还可以发现 this 很有用。

【讨论】:

    【解决方案3】:

    使用select 系统调用,并根据需要设置timeout 参数。 Beej's guide 仍然是一个很好的来源,其中包含大量示例代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 2010-10-31
      • 2013-10-15
      • 1970-01-01
      • 2011-09-13
      相关资源
      最近更新 更多