今天主要想说道说道boost里面的网络通信库如何设计和使用,因为最近一直在和网络一起工作,大数据处理和机器学习都离不开最后使用网络进行上线部署。先看看全部的源代码吧。
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include <stdint.h>
#include "data.h"
#include <ostream>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
using boost::asio::ip::tcp;
class session
: public std::enable_shared_from_this < session >
{
public:
session(boost::asio::ip::tcp::socket socket)
: socket_(std::move(socket))
{
}
void start()
{
do_read();
}
private:
void do_read()
{
auto self(shared_from_this());
//int32_t data_length;
boost::asio::async_read(socket_,
boost::asio::buffer(&data_length, 4),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_read_body();
}
});
}
void do_read_body()
{
auto self(shared_from_this());
boost::asio::async_read(socket_,
buf_, boost::asio::transfer_exactly(data_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
std::cout << length<<std::endl;
if (!ec)
{
ProcessMessage();
do_read();
}
else
{
std::cout << "error" << std::endl;
}
});
};
void ProcessMessage()
{
boost::archive::binary_iarchive ia(buf_);
translate_data message;
ia >> message;
std::cout << message.width<<std::endl;
};
int32_t data_length;
boost::asio::ip::tcp::socket socket_;
boost::asio::streambuf buf_;
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: acceptor_(io_service, boost::asio::ip::tcp::endpoint(tcp::v4(), port)),
socket_(io_service)
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
std::make_shared<session>(std::move(socket_))->start();
}
do_accept();
});
}
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ip::tcp::socket socket_;
};
int main(int argc, char* argv[])
{
try
{
/*if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}*/
boost::asio::io_service io_service;
server s(io_service, 8888);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
这个就是服务区的全部源代码。
data是消息的数据格式,translate_data 这个类的定义,该类可以使用boost进行序列化。整个消息处理起来非常的流畅,可以使得我们只关心数据流,而忽略服务器如何异步接收消息。当然我的示例代码中的数据格式非常之简单,数据包开头的int表示数据有多少个字节。索性连我的消息代码一起放出来:
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
struct MeasurementZ
{
double m_a[3];
double m_w[3];
double m_t;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::make_array(m_a, 3 * sizeof(double));
ar & boost::serialization::make_array(m_w, 3 * sizeof(double));
ar & m_t;
}
};
struct translate_data
{
int width;
int height;
double mt;
int N;
unsigned char* buffer;//640*480;
std::vector<MeasurementZ> z;
std::vector<double> Quaterniond;//4
std::vector<double> Vector3d;//3
double M_rM_t;
};
BOOST_SERIALIZATION_SPLIT_FREE(translate_data)
namespace boost
{
namespace serialization
{
/** Serialization support for cv::Mat */
template<class Archive>
void save(Archive & ar, const translate_data& m, const unsigned int version)
{
ar & m.width;
ar & m.height;
ar & m.mt;
ar & m.N;
const size_t data_size = m.width * m.height*sizeof(unsigned char);
ar & boost::serialization::make_array(m.buffer, data_size);
ar & m.z;
ar & m.Quaterniond;
ar & m.Vector3d;
ar & m.M_rM_t;
} /** Serialization support for cv::Mat */
template <class Archive>
void load(Archive & ar, translate_data& m, const unsigned int version)
{
ar & m.width;
ar & m.height;
ar & m.mt;
ar & m.N;
const size_t data_size = m.width * m.height*sizeof(unsigned char);
m.buffer = new unsigned char[m.width*m.height];
ar & boost::serialization::make_array(m.buffer, data_size);
ar & m.z;
ar & m.Quaterniond;
ar & m.Vector3d;
ar & m.M_rM_t;
}
}
};
整个工程非常简单,请实用c++11标准来完成。