在http://www.godebug.org/index.php/archives/105/的基础上改了一点.
客户端:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include "protocal.h"
void read_buf(boost::asio::ip::tcp::socket& s, boost::asio::streambuf& buf)
{
int size = 0;
boost::asio::read(s, boost::asio::buffer(&size, sizeof(int)));// 先读取发送来服务端的缓冲区的大小
if (size == 0)
{
std::cout << "No data...." << std::endl;
return;
}
boost::asio::read(s, buf, boost::asio::transfer_exactly(size)); // 读取缓冲区中的内容
}
void write_buf(boost::asio::ip::tcp::socket& s, boost::asio::streambuf& buf)
{
int size = buf.size(); // 要发送的缓冲区大小
boost::asio::write(s, boost::asio::buffer(&size, sizeof(int))); // 先发送缓冲区的大小
boost::asio::write(s, buf, boost::asio::transfer_exactly(size)); // 再发送指定的message_t的大小
}
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 8001);
boost::asio::ip::tcp::socket s(io_service);
boost::asio::connect(s, &ep);
message_t message;
std::cout << "Enter a number:";
std::cin >> message.num;
std::cout << "Enter a message:";
std::cin >> message.str;
boost::asio::streambuf buf1;
boost::archive::binary_oarchive oa(buf1);
oa << message;
write_buf(s, buf1);
boost::asio::streambuf buf2;
read_buf(s, buf2);
boost::archive::binary_iarchive ia(buf2);
int rep_num = 0;
ia >> rep_num;
for (int i = 0; i < rep_num; ++i)
{
message_t recv_msg;
ia >> recv_msg;
std::cout << "Number:" << recv_msg.num;
std::cout << "Message:" << recv_msg.str << std::endl;
}
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
服务端:
#include <random>
#include <cstdlib>
#include <iostream>
#include <functional>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include "protocal.h"
// using boost::asio::ip::tcp;
class session
{
public:
session(boost::asio::io_service& io_service) : socket_(io_service) {}
boost::asio::ip::tcp::socket& socket()
{
return socket_;
}
void start()
{
async_read_buf(buf_, boost::bind(&session::handle_read_message, this, _1));
}
private:
void handle_read_message(boost::system::error_code ec)
{
if (ec)
{
delete this;
return;
}
boost::archive::binary_iarchive ia(buf_);
message_t msg;
ia >> msg; //得到message结构体
std::cout << msg.str << std::endl;
buf_.consume(buf_.size());//清空buf
boost::archive::binary_oarchive oa(buf_);
std::uniform_int_distribution<unsigned> u(1, 10); // 分部类型(生成1-10之间均匀分布的随机数)
std::default_random_engine e; // 生成无符号随机整数
int num = u(e); //生成返回的message结构体的数量
oa << num; //加上数量
for (int i = 0; i < num; ++i)
{
oa << msg;
}
async_write_buf(buf_, [this](boost::system::error_code){ delete this; });
}
private:
//回调函数
typedef std::function<void(boost::system::error_code ec)> callback_t;
//读取buf
void async_read_buf(boost::asio::streambuf& buf, callback_t callback)
{
boost::asio::async_read(socket_, boost::asio::buffer(&size_, sizeof(int)),
boost::bind(&session::handle_read_size,this, boost::ref(buf), callback, boost::asio::placeholders::error));
}
void handle_read_size(boost::asio::streambuf& buf, callback_t callback, boost::system::error_code ec)
{
if (ec)
{
delete this;
return;
}
boost::asio::async_read(socket_, buf, boost::asio::transfer_exactly(size_),
boost::bind(callback, boost::asio::placeholders::error));
}
//写入buf
void async_write_buf(boost::asio::streambuf& buf, callback_t callback)
{
size_ = buf.size();
boost::asio::async_write(socket_, boost::asio::buffer(&size_, sizeof(int)),
boost::bind(&session::handle_write_size,this, boost::ref(buf), callback, boost::asio::placeholders::error));
}
void handle_write_size(boost::asio::streambuf& buf, callback_t callback, boost::system::error_code ec)
{
if (ec)
{
delete this;
return;
}
boost::asio::async_write(socket_, buf, boost::asio::transfer_exactly(size_),
boost::bind(callback, boost::asio::placeholders::error));
}
int size_;
boost::asio::streambuf buf_;
boost::asio::ip::tcp::socket socket_;
};
class server
{
public:
server(boost::asio::io_service& io_service, short port = 8001)
: io_service_(io_service),
acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
{
start_accept();
}
private:
void start_accept()
{
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(session* new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
}
else
{
delete new_session;
}
start_accept();
}
boost::asio::io_service& io_service_;
boost::asio::ip::tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
server s(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
最后再加上一个头文件: protocal.h
#pragma once
#include <boost/serialization/access.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
struct message_t
{
int num;
std::string str;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /*version*/)
{
ar & num;
ar & str;
}
};
运行结果: 多个客户端同时连接服务端后