【问题标题】:Use socket io in C++ for dynamic number of bytes在 C++ 中使用套接字 io 获取动态字节数
【发布时间】:2018-11-30 06:19:11
【问题描述】:

我正在尝试实现一个简单的客户端-服务器应用程序,其中客户端或服务器可以在单个 write() 调用中发送动态字节数。

例如,假设客户端发送一个 1500 字节的字节流。服务器每 1000 个字节读取一次。

int BUFFER_SIZE = 1000;
...
read( iSockFD, cBuffer, BUFFER_SIZE );

我可以使用循环并调用 read,直到它的返回值为 0。但是客户端可能在一个循环中有多个write()调用(即发送多条消息)。

我的问题是,它会影响服务器端的read() 吗?意思是,客户端的两个连续的 1000 字节的 write() 会被服务器端的 2000 字节缓冲区大小的单个 read() 读取吗?

如果是这样,那么推荐的实现这种场景的方法是什么?我应该对消息使用分隔符(使用编码算法)吗?

我理解这与套接字本身而不是 C++ 更相关。但是,我们非常感谢您的帮助和指导。

更新

目的是实现一个简单的中间件系统来发送不同类型的消息,其中消息在发送之前将被编码为二进制。

【问题讨论】:

  • 你必须使用一些协议来通知服务器应该读取多少字节。
  • 不过,它会保证一个write() 触发一个read() 吗?
  • 以一定的字节数和字节序(通常为 4 字节,按网络字节顺序)发送大小。
  • 粘包问题。使用 TCP,您需要实现自己的方式来打包和解包数据。它可能是一个类型-长度-数据包。
  • 还是保证一写()触发一读()不行。

标签: c++ sockets network-programming


【解决方案1】:

没有人能保证一个 write(x) 会在接收端触发一个 read(x)。如果 x 大于您的套接字接收缓冲区,或者如果您在套接字接收缓冲区中接收到整个消息之前调用 read(),则 read() 将仅返回一小部分数据并要求您发出后续读取() 得到其余的。

推荐的方法是定义一个足够大的消息缓冲区。每次调用 read() 都将返回 1 个或更多字节,您会一直将其排入缓冲区。现在,一旦缓冲区大于 4 个字节 + 存储在缓冲区前 4 个字节中的 be32toh(integer) ,您必须消耗整数加上缓冲区开头的以下 x 个字节(并进一步处理它们)。这将允许您很好地处理 read() 包含以前未完成的数据包的结尾并同时包含下一个(不完整)数据包的开头的情况。

只需确保您传输的每个有效负载都以 htobe32(length) 开头。

【讨论】:

  • 为什么只转换长度(关于字节序)?为什么不是有效载荷?
  • 因为你没有说你传输什么样的有效载荷!如果您传输 Protobuf,则无需担心字节顺序。如果你传输一个字符流,你也不需要!如果你传输整数,你会这样做!
  • 是的,很抱歉。我的目的是将对象转换为二进制并传输。我想那我也不必担心。对吗?
猜你喜欢
  • 2016-05-17
  • 1970-01-01
  • 2012-10-10
  • 2018-05-15
  • 2015-02-12
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 2020-10-20
相关资源
最近更新 更多