有了客户端的扫雷,创建服务端还是比较顺畅的,直接将客户端需要include的头文件加进来,额外添加一个#include <boost/bind.hpp>头文件(注:#include <boost/bind.hpp>文件未包含在#include <boost/asio.hpp>中.)由于asio服务端需要在一个线程中启动异步操作,即一个死循环等待socket事件,因此需要创建一个线程,这里使用QT的线程支持即可.创建QThread的子类,重写其run()虚函数,在里面调用io_service::run();在将asio自带的tcp异步echo服务代码全部移植过来,测试通过.
//asiotcpserverthread.h头文件,其中声明了线程类及从控制台范例中移植过来的类
#ifndef ASIOTCPSERVERTHREAD
#define ASIOTCPSERVERTHREAD
//asio
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio/ip/address_v6.hpp>
#include <boost/asio/ip/basic_endpoint.hpp>
#include <boost/asio/ip/basic_resolver.hpp>
#include <boost/asio/ip/basic_resolver_entry.hpp>
#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/impl/connect.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/bind.hpp>
#include <boost/asio/placeholders.hpp>
//qt
#include <QThread>
using boost::asio::ip::tcp;
class AsioTcpServerThread : public QThread
{
public:
AsioTcpServerThread(void);
~AsioTcpServerThread(void);
protected:
void run();
};
class session
{
public:
session(boost::asio::io_service& io_service);
tcp::socket& socket();
void start();
private:
void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
void handle_write(const boost::system::error_code& error);
tcp::socket socket_;
enum {max_length = 1024};
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port);
private:
void start_accept();
void handle_accept(session* new_session, const boost::system::error_code& error);
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
const int port = 10800;
#endif
//asiotcpserverthread.cpp 线程类及移植类的实现
#include "asiotcpserverthread.h"
AsioTcpServerThread::AsioTcpServerThread()
{
}
AsioTcpServerThread::~AsioTcpServerThread()
{
}
void AsioTcpServerThread::run()
{
try
{
boost::asio::io_service io_service;
server s(io_service, port);
io_service.run();
}
catch(std::exception& e)
{
}
}
session::session(boost::asio::io_service& io_service) : socket_(io_service)
{
}
tcp::socket& session::socket()
{
return socket_;
}
void session::start()
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));//异步读取完毕后调用handle_read函数
}
void session::handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if(!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this, boost::asio::placeholders::error));//写完毕后调用handle_write函数
}
else
{
delete this;
}
}
void session::handle_write(const boost::system::error_code &error)
{
if(!error)
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
server::server(boost::asio::io_service &io_service, short port)
: io_service_(io_service), acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
start_accept();
}
void server::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 server::handle_accept(session *new_session, const boost::system::error_code &error)
{
if(!error)
{
new_session->start();
}
else
{
delete new_session;
}
start_accept();
}
//界面头文件
#ifndef QT_BOOST_SERVER_H
#define QT_BOOST_SERVER_H
#include <QtGui/QMainWindow>
#include "ui_qt_boost_server.h"
#include "asiotcpserverthread.h"
class qt_boost_server : public QMainWindow
{
Q_OBJECT
public:
qt_boost_server(QWidget *parent = 0, Qt::WFlags flags = 0);
~qt_boost_server();
private:
Ui::qt_boost_serverClass ui;
AsioTcpServerThread *tcpServer;
private slots:
void pbStartServerClicked();
};
#endif // QT_BOOST_SERVER_H
//界面实现类 点击按钮启动线程
#include "qt_boost_server.h"
qt_boost_server::qt_boost_server(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect(ui.pbStartServer, SIGNAL(clicked()), this, SLOT(pbStartServerClicked()));
tcpServer = new AsioTcpServerThread();
}
qt_boost_server::~qt_boost_server()
{
}
void qt_boost_server::pbStartServerClicked()
{
tcpServer->start();
}