繁体   English   中英

C socket原子无阻塞读取

[英]C socket atomic non-blocking read

我正在实现一个TCP / IP服务器应用程序,该应用程序在边缘触发模式下使用epoll并执行无阻塞套接字操作。 客户端使用没有epoll的简单阻止操作。

我看不到如何在服务器端实现“原子读取”。 为了解释我对“原子读取”的含义,请参见带有简单阻塞操作的示例:

  • 客户端和服务器都使用64K缓冲区。 (在应用程序级别。它们不会更改内核级别的套接字缓冲区。)
  • 客户端通过一次写入操作即可写入12K数据。
  • 服务器读取它。 在这种情况下,当缓冲区相同时,它将始终读取整个12K。 因此它不能只读取一半。 这就是我所说的“原子”。

但是在epoll +非阻塞操作的情况下,可能会发生以下情况:

  • 客户端和服务器都使用64K缓冲区。 (在应用程序级别。它们不会更改内核级别的套接字缓冲区。)
  • 客户端通过一次写入操作即可写入12K数据。
  • 6K到达服务器
  • epoll告知应用程序数据已到达套接字
  • 应用程序使用非阻塞操作将6K读入缓冲区。
  • 重复读取时,它将返回EAGAIN / EWOULDBLOCK。

在这种情况下,读取的内容不是“原子的”。 不保证当通过单个写操作写入数据时,读取将一次返回整个数据。

是否可以知道数据何时是部分数据? 我知道一种解决方案是始终将数据大小附加到开头,或者另一种解决方案是始终关闭并重新打开连接,但是我不想这样做:因为我认为内核必须知道不是完整的因为它保证了阻塞操作的原子性,所以“程序包”(该单元如何称为BTW?)到来了。

非常感谢!

TCP是基于流的,而不是面向消息的。 即使在阻塞套接字的情况下,也不能保证应用程序发送的消息一劳永逸。 TCP将决定自己的路线。

因此,由应用程序对其“希望”进行“原子”读取。 例如:

应用协议应规定消息应以长度字节为前缀。 长度字节通知对等体感兴趣的应用程序数据的大小。 当然,应用程序应该知道两字节长度指示符何时开始。

[2字节的味精长度] [感兴趣的数据字节]

基于此信息,正在读取的应用程序应采取措施。 它应该轮询套接字,直到接收到所有由msg长度字节指示的字节为止。 只有这样才能处理数据。

如果需要“原子”读取而不是部分读取,则可以在recv使用MSG_PEEK标志。 这不应从套接字缓冲区中删除数据。 应用程序窥探套接字,根据返回值查看套接字缓冲区中是否需要所需数据数。

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM