通过boost::asio::tcp::ip发送的大正文
Large body sent via boost::asio::tcp::ip
我的协议很简单:我发送了一个size_t
,指示正文的大小,然后是正文本身。
代码基于官方Boost示例,如下:
class tcp_conn :
public std::enable_shared_from_this<tcp_conn>,
private boost::noncopyable
{
public:
tcp_conn(ba::io_service& io_service);
void start();
void stop();
tcp::socket& socket();
private:
void handle_read_header(const error_code& e, std::size_t bytes_transferred);
void handle_read(const error_code& e, std::size_t bytes_transferred);
ba::streambuf::mutable_buffers_type buffer_wrapper_;
ba::streambuf buffer_;
std::size_t buffer_size_;
tcp::socket socket_;
};
实现为:
void tcp_conn::start() {
socket_.async_read_some(
ba::buffer(&buffer_size_, sizeof(buffer_size_)),
boost::bind(
&tcp_conn::handle_read_header,
this,
ba::placeholders::error,
ba::placeholders::bytes_transferred
)
);
}
void tcp_conn::handle_read_header(const boost::system::error_code& e, std::size_t bytes_transferred){
if(!e) {
buffer_wrapper_ = buffer_.prepare(buffer_size_);
socket_.async_read_some(
ba::buffer(buffer_wrapper_),
boost::bind(
&tcp_conn::handle_read,
this,
ba::placeholders::error,
ba::placeholders::bytes_transferred
)
);
} else {
//stop connection
}
}
void tcp_conn::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) {
if (!e ) {
buffer_.commit(bytes_transferred);
if(buffer_.size() == buffer_size_) {
std::cout << "WHOLE BODY TRANSFERED NOW" << std::endl;
//has all data in buffer, handle it.
}
else {
std::cout << "NOT WHOLE BODY TRANSFERED, still got "<< (buffer_size_ - bytes_transferred) << " to go" << std::endl;
socket_.async_read_some(
ba::buffer(buffer_wrapper_),
boost::bind(
&tcp_conn::handle_read,
this,
ba::placeholders::error,
ba::placeholders::bytes_transferred
)
);
}
}
else {
//handle error
}
}
这个不太管用。我猜我的错误是在buffer_wrapper_
的递归更新的某个地方-一些数据丢失,覆盖?
buffer_.commit()
使prepare()
的结果无效,如文档所述:"返回的对象被任何修改输入序列或输出序列的basic_streambuf成员函数无效。"
实际上,不需要手动准备缓冲区并链接async_read_some()
,您只需使用streambuf
和完成条件的适当的helper free函数:
asio::async_read(
socket_,
buffer_,
asio::transfer_exactly(buffer_size_),
boost::bind(&tcp_conn::handle_read, this, _1, _2)
);
这样,当您获得整个消息正文或发生错误时,就会调用handle_read
。
相关文章:
- 我正在开发服务器,ip作为参数传递不起作用
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- Azure Kinect 使用正文索引映射裁剪正文
- C++ boost::asio::ip::tcp::acceptor 有时不接受连接器?
- 从网址获取 IP (C++)
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- 如何修复无效的API密钥,IP或操作权限错误?
- 为什么调用没有正文的纯虚拟方法不会导致链接器错误?
- 获取加密的正文响应WinHttp HTTPS
- C++ Winsock2 客户端未通过远程 IP 连接到服务器
- PHP Profiler语言 - 使用 C++ 从 PHP 扩展获取客户端 IP 和 URL
- 为什么 boost::asio::ip::tcp::basic_stream_socket::available 的运行
- 如何使用 libcurl 在本地 IP 上获取 HTML?
- 如何 Lambda 线程正文
- 在C++中使用宏验证 IP 时出错
- 使用 IP 帮助程序的 Windows 中活动 UDP 连接的远程地址
- 将静态 IP 分配给我的 ESP32 服务器后不再响应
- C++ / Qt:如何检测主机名或IP地址何时引用当前系统?
- 通过boost::asio::tcp::ip发送的大正文