- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
让我们假设一个客户端持有两个不同的大对象(根据字节大小)并序列化它们,然后发送序列化的对象 使用 boost::asio
通过 TCP/IP 网络连接到服务器。
对于客户端实现,我使用 boost::asio::write
将二进制数据 (const char*
) 发送到服务器。
对于服务器端实现,我使用 read_some
而不是 boost::asio::ip::tcp::iostream
来提高效率.我在服务器端构建了以下 recv
函数。第二个参数 std::stringstream &is
在函数末尾保存了一个大的接收数据(>65536 字节)。
当客户端顺序调用两个boost::asio::write
以分别发送两个不同的二进制对象时,服务器端顺序调用两个相应的recv
作为出色地。但是,第一个 recv
函数吸收了所有两个传入的大数据,而第二个调用什么也没收到 ;-(。我不确定为什么会发生这种情况以及如何解决。
由于两个不同的对象中的每一个都有自己的(反)序列化功能,我想分别发送每个数据。事实上,由于有超过 20 个对象(不仅仅是 2 个)必须通过网络发送。
void recv (
boost::asio::ip::tcp::socket &socket,
std::stringstream &is) {
boost::array<char, 65536> buf;
for (;;) {
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
std::cout << " read "<< len << " bytes" << std::endl; // called multiple times for debugging!
if (error == boost::asio::error::eof)
break;
else if (error)
throw boost::system::system_error(error); // Some other error.
std::stringstream buf_ss;
buf_ss.write(buf.data(), len);
is << buf_ss.str();
}
}
客户端主文件:
int main () {
... // some 2 different big objects are constructed.
std::stringstream ss1, ss2;
... // serializing bigObj1 -> ss1 and bigObj2-> ss2, where each object is serialized into a string. This is due to the dependency of our using some external library
const char * big_obj_bin1 = reinterpret_cast<const char*>(ss1.str().c_str());
const char * big_obj_bin2 = reinterpret_cast<const char*>(ss2.str().c_str());
boost::system::error_code ignored_error;
boost::asio::write(socket, boost::asio::buffer(big_obj_bin1, ss1.str().size()), ignored_error);
boost::asio::write(socket, boost::asio::buffer(big_obj_bin2, ss2.str().size()), ignored_error);
... // do something
return 0;
}
服务器主文件:
int main () {
... // socket is generated. (communication established)
std::stringstream ss1, ss2;
recv(socket,ss1); // this guy absorbs all of incoming data
recv(socket,ss2); // this guy receives 0 bytes ;-(
... // deserialization to two bib objects
return 0;
}
最佳答案
recv(socket,ss1); // this guy absorbs all of incoming data
当然它吸收了一切。您显式编码recv
以执行无限循环,直到eof
。那是流的结尾,这意味着“每当套接字在远程端关闭时”。
所以协议(protocol)中缺少的基本内容是框架。最常见的解决方法是:
发送“特殊序列”来分隔帧。在文本中,一个常见的特殊分隔符是 '\0'
。但是,对于二进制数据,(非常)很难找到一个不能自然出现在有效负载中的分隔符。
当然,如果您知道有效载荷的额外特征,您可以使用它。例如。如果您的有效负载被压缩,您知道您不会经常找到 512 个相同字节的 block (它们会被压缩)。或者,您可以采用消除歧义的方式对二进制数据进行编码。 yEnc
, Base122
等。想到(请参阅 Binary Data in JSON String. Something better than Base64 获取灵感)。
不管怎样
手写阅读循环很笨拙。接下来,非常没有必要这样做并且无论如何也将 block 复制到字符串流中。如果您无论如何都要进行所有复制,只需将 boost::asio::[async_]read
与 boost::asio::streambuf
直接一起使用即可。
这很清楚UB :
const char * big_obj_bin1 = reinterpret_cast<const char*>(ss1.str().c_str());
const char * big_obj_bin2 = reinterpret_cast<const char*>(ss2.str().c_str());
str()
returns a temporary copy of the buffer - 这不仅是一种浪费,而且意味着 const char*
在它们被初始化的那一刻就悬空。
关于c++ - 我们如何从 boost::asio::tcp::ip::read_some 调用中顺序接收多个数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48998084/
我有一些客户端 asio 代码使用 read_some() 直到读取了字节数。但是通过查看所有示例,我无法弄清楚如何将读取缓冲区组装成包含整个消息的更大缓冲区。我该怎么做? boost::array
我正在使用 boost asio 库实现一个 tcp 服务器。在服务器端,我使用asio::async_read_some获取数据,使用asio::write写入数据。服务器代码是这样的。 std::
我有以下使用 boost asio read_some 函数从 TCP 套接字读取的代码。目前代码是同步的,我需要将其转换为异步版本。问题最初是读取了一些字节以识别数据包类型并获取数据包的长度。然后我
下面的代码绝对有效,但速度不如我预期。 我希望我的程序能够以非常快的速度读取数据。还有另一个商业应用程序连接到同一台服务器并以惊人的速度检索数据。服务器端不是问题。 class A { //.
我开始使用 Boost Asio 的 TCP 套接字。 read_some 和有什么区别和 receive和 write_some 有什么区别?和 send ?谢谢! 最佳答案 据我所知,read_s
我们可以用这样的东西在套接字上超时读取: #include #include //... void http_request::set_result(boost::optional* a, boo
此示例基于书 Boost.Asio C++ Network Programming 中的第 1 章书。我正在尝试使用 Boost.Asio 库构建一个简单的客户端和同步服务器。 这是客户端代码 #de
让我们假设一个客户端持有两个不同的大对象(根据字节大小)并序列化它们,然后发送序列化的对象 使用 boost::asio 通过 TCP/IP 网络连接到服务器。 对于客户端实现,我使用 boost::
我已经使用 boost::asio 实现了一个 TCP 服务器。此服务器使用 basic_stream_socket::read_some 函数读取数据。我知道 read_some 不保证提供的缓冲区
所以通常我们会做这样的事情 socket.read_some(boost::asio::buffer(buffer, buffer_size)); 但是如何让它在读取还没有开始的情况下抛出异常比说 3
我将 Boost.Asio 用作简单的套接字库。 当我打开一个套接字时,我创建了一个线程,该线程不断读取该套接字,并在套接字关闭或发生其他一些错误时返回。 while((read = socket->
我正在尝试构建一个客户端以通过特定协议(protocol)从服务器获取数据。我知道我的代码不是最好的 - 但目前我仍在试验 Boost ASIO 的基本功能。 我想从 TCP-Function 中实现
我是一名优秀的程序员,十分优秀!