【问题标题】:Set TCP client socket to non-blocking: Server vs client将 TCP 客户端套接字设置为非阻塞:服务器与客户端
【发布时间】:2016-03-18 07:45:02
【问题描述】:

我有一个关于 TCP 连接中的非阻塞套接字的问题。

我已经实现了两个 c++ 类,一个用于 tcp 服务器,一个用于客户端。服务器有两个套接字文件描述符,一个用于服务器,一个用于客户端。客户端有一个套接字文件描述符。

我的服务器异步运行,我的客户端以固定速率运行。因此,我想要一个非阻塞套接字,用于将数据从客户端发送到服务器,s.t.客户端可以以固定的速率发送数据而不会停止,服务器异步读取同时缓存的所有数据。

所以我的问题是:如果我在客户端或服务器类中将客户端套接字设置为非阻塞,会有什么不同吗?(使用fcntl(this->newsockfd_, F_SETFL, fcntl(this->newsockfd_, F_GETFL, 0) | O_NONBLOCK),其中this->newsockfd_ 是两个类中客户端的套接字文件描述符)

我在我的程序中尝试过这个,似乎在客户端类中将客户端套接字设置为非阻塞并没有成功,但在服务器类中设置它可以。但是,我不明白为什么这会有所作为。

【问题讨论】:

  • 有什么不同?将套接字设置为非阻塞意味着套接字读取、写入和其他套接字操作将立即返回。然后,您必须准备好处理没有数据传输的情况,因为操作通常会因为没有可读取的数据而阻塞,或者出站网络缓冲区已满等。

标签: c++ sockets tcp


【解决方案1】:

如果您的套接字设置为非阻塞模式,您将得到这样的结果。它永远不会阻塞。但这并不意味着您的 api 调用会成功。

后台正在使用缓冲区,如果它们已满,这意味着在阻塞模式下套接字会阻塞,您将获得返回码 EWOULDBLOCK,这意味着您的发送失败。这意味着您基本上必须等待缓冲区清空然后重试。

不管服务器的接收速率如何,您以均匀速率发送的想法是不可能的。您不能让客户端以固定速率发送。 TCP的整个想法是客户端和服务器之间不断协商,速度将在很大程度上取决于网络条件。拥堵等。

迁移到非阻塞套接字会产生一些问题。您必须检测发送失败,您必须检查套接字是否再次变为可写,您必须存储您尝试发送的字节,并在套接字再次变为可写时重新尝试发送。

在客户端和服务器上使用阻塞和非阻塞套接字有很大的不同。在我看来,非阻塞套接字更难处理。您需要 select api,超时很可能检测到所有可能的套接字状态。在阻塞套接字的情况下,您可以只在线程中使用套接字,如果套接字阻塞,则也只是线程将阻塞。如果您的 gui 在不同的线程上,则 GUI 将响应。

【讨论】:

    【解决方案2】:

    由于您的客户端仅发送数据,因此非阻塞设置不会对其产生影响。根据关于套接字编程的优秀beej.us guide,只有对accept()recv() 的调用受非阻塞设置的影响。由于只有您的服务器在调用这些,您会看到服务器代码的更改。如果您的客户端收到数据,则非阻塞设置会影响它,您必须使用select() 检查是否有数据并相应地从中读取。

    【讨论】:

    • 这个答案是错误的,因为发送也可以阻止。 beej 说很多功能块。接受()块。所有 recv() 函数块。 accept 和 recv 不是很多函数,只是两个可以阻塞的函数示例。如前所述,发送也可以阻止。
    • 您的引文并未说明您的主张,第三方网站也不是规范性参考。您应该引用 man 页面或 Posix,它们也没有这么说。
    猜你喜欢
    • 2017-04-18
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 2016-02-07
    相关资源
    最近更新 更多