异步发送和接收带有提升的自定义数据包?



我正在尝试使用 boost 异步发送和接收自定义数据包,根据我当前的实现,我有一些问题:

TCP客户端.cpp

#include "tcpclient.h"
#include <boost/chrono.hpp>
#include "../utils/logger.h"
tcpclient::tcpclient(std::string host, int port) :
_endpoint(boost::asio::ip::address::from_string(host), port), _socket(_ioservice) {
logger::log_info("Initiating client ...");
}
void tcpclient::start() {
connect();
_ioservice.run();
}
void tcpclient::connect() {
_socket.async_connect(_endpoint, std::bind(&tcpclient::connect_handler, this, std::placeholders::_1));
}
void tcpclient::receive() {
boost::asio::async_read(_socket, boost::asio::buffer(data, HEADER_LEN), std::bind(&tcpclient::read_handler, this, std::placeholders::_1));
}
void tcpclient::connect_handler(const boost::system::error_code &error) {
if (!error) {
_status = CONNECTED;
logger::log_info("Connected to " + get_remote_address_string());
receive();
} else {
_status = NOT_CONNECTED;
_socket.close();
_timer.expires_from_now(boost::asio::chrono::seconds{2});
_timer.async_wait(std::bind(&tcpclient::reconnect_handler, this, std::placeholders::_1));
logger::log_info("Failed to connect");
}
}
void tcpclient::reconnect_handler(const boost::system::error_code &error) {
connect();
}
void tcpclient::read_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
logger::log_info("reading some data?");
}

std::string tcpclient::get_remote_address_string() {
return _socket.remote_endpoint().address().to_string() + ":" + std::to_string(_socket.remote_endpoint().port());
}

tcpclient.h

#include <string>
#include <boost/asio.hpp>

enum ConnectionStatus{
NOT_CONNECTED,
CONNECTED
};

class tcpclient {
public:
tcpclient(std::string host, int port);
void start();
void connect();
private:
ConnectionStatus _status = NOT_CONNECTED;
const int HEADER_LEN = 0x01;
void receive();
void connect_handler(const boost::system::error_code& error);
void reconnect_handler(const boost::system::error_code &error);
void read_handler(const boost::system::error_code& error);
std::string get_remote_address_string();

boost::asio::io_service _ioservice;
boost::asio::ip::tcp::endpoint _endpoint;
boost::asio::ip::tcp::socket _socket;
boost::asio::steady_timer _timer{_ioservice, boost::asio::chrono::seconds{2}};
};

1)添加两个单独的读取和写入处理程序是否有意义,一个用于标头,一个用于正文?

2) 如何确保我可以同时发送和接收数据而不会遇到任何问题?这需要多个套接字吗?这些功能通常如何实现?

3) 我将如何发送自定义数据结构?我想实现自定义数据包结构。我将如何发送此类对象,boost 是否有内置的序列化程序?如何发送和接收自定义数据结构?

4) 如果在发送或接收数据期间连接断开会发生什么?是否通过检查 eof 的错误代码对象直接在接收/发送处理程序中处理此类异常?

一个基本的例子会有很大帮助!

1)添加两个单独的读取和写入处理程序是否有意义,一个用于标头,一个用于正文?

是的。代码不同,不同的处理程序是最佳实践。

2) 如何确保我可以同时发送和接收数据而不会遇到任何问题?

异步操作。函数会立即返回,因此唯一的延迟是网络速度。

3) 我将如何发送自定义数据结构?

boost::asio::buffer支持发送/接收原始内存字节。当这还不够时,asio 有序列化:

  • https://www.boost.org/doc/libs/1_70_0/libs/serialization/doc/index.html
  • https://www.boost.org/doc/libs/1_70_0/libs/serialization/example/demo.cpp

4) 如果在发送或接收数据期间连接断开会发生什么?

所有读取和写入操作都返回一个boost::system::error_code。如果发生错误,必须关闭套接字(如果可能,请重新连接)。一些基本代码:

void AfterReadingHeader(const boost::system::error_code & aError)
{
if (aError)
{
// something went wrong 
boost::system::error_code error;
socket.shutdown(tcp::socket::shutdown_receive, error);
socket.close(error);
}
...
}

最新更新