1.什么是asio?
Asio是一个用于网络底层I / O编程的跨平台C ++开发的网络编程库,支持同步与异步的网络开发。
2.asio有哪些优点?
简单易用、跨平台、可以用于大型项目中。
3.Asio的io_service作用?
io_service实例同底层操作系统的IO服务进行交互,是asio框架中的调度器,所有异步io事件都是通过它来分发处理的。Io_service提供了两个方法post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。Io_service是完全线程安全的队列

4.以下asio常用的函数?
async_connect(endpoint)://这个函数用异步的方式连接到一个地址。
async_accept(socket,accept_handler) //接收新客户端连接。
read(stream, buffer [, extra options])//同步读取方法。
async_read(stream, buffer [, extra options], handler)//异步读取方法。
write(stream, buffer [, extra options]) //同步发送。
async_write(stream, buffer [, extra options], handler) //异步发送。

Asio聊天室例子:
服务器端:

//chat_message.h
#ifndef CHAT_MESSAGE_HPP
#define CHAT_MESSAGE_HPP
#include "Header.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "stdafx.h"class chat_message {
public:enum { header_length = sizeof(Header) };enum { max_body_length = 512 };chat_message(){}const char *data() const { return data_; }char *data() { return data_; }std::size_t length() const { return header_length + m_header.bodySize; }const char *body() const { return data_ + header_length; }char *body() { return data_ + header_length; }int type() const { return m_header.type; }std::size_t body_length() const { return m_header.bodySize; }void setMessage(int messageType, const void *buffer, size_t bufferSize) {assert(bufferSize <= max_body_length);m_header.bodySize = bufferSize;m_header.type = messageType;std::memcpy(body(), buffer, bufferSize);std::memcpy(data(), &m_header, sizeof(m_header));}void setMessage(int messageType, const std::string& buffer) {setMessage(messageType, buffer.data(), buffer.size());}bool decode_header() {std::memcpy(&m_header, data(), header_length);if (m_header.bodySize > max_body_length) {std::cout << "body size " << m_header.bodySize << " " << m_header.type<< std::endl;return false;}return true;}
private:char data_[header_length + max_body_length];Header m_header;
};#endif 
//Header.h#ifndef FND_STRUCT_HEADER_H
#define FND_STRUCT_HEADER_H
#include <string>
struct Header{int bodySize;int type;
};
enum MessageType
{MT_BIND_NAME = 1,MT_CHAT_INFO = 2, MT_ROOM_INFO = 3, };
struct BindName{char name[32];int nameLen;
};
struct ChatInformation {char information[256];int infoLen;
};
struct RoomInformation {BindName name;ChatInformation chat;
};
bool parseMessage(const std::string &input, int *type, std::string &outbuffer);
#endif//Header.cpp
#include "stdafx.h"
#include "Header.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
bool parseMessage(const std::string &input, int *type, std::string &outbuffer) {auto pos = input.find_first_of(" ");if (pos == std::string::npos)return false;if (pos == 0)return false;auto command = input.substr(0, pos);if (command == "BindName") {std::string name = input.substr(pos + 1);if (name.size() > 32)return false;if (type)*type = MT_BIND_NAME;BindName bindInfo;bindInfo.nameLen = name.size();std::memcpy(&(bindInfo.name), name.data(), name.size());auto buffer = reinterpret_cast<const char *>(&bindInfo);outbuffer.assign(buffer, buffer + sizeof(bindInfo));return true;} else if (command == "Chat") {std::string chat = input.substr(pos + 1);if (chat.size() > 256)return false;ChatInformation info;info.infoLen = chat.size();std::memcpy(&(info.information), chat.data(), chat.size());auto buffer = reinterpret_cast<const char *>(&info);outbuffer.assign(buffer, buffer + sizeof(info));if (type)*type = MT_CHAT_INFO;return true;}return false;
}
//chat.cpp
#include "chat_message.h"
#include <asio.hpp>
#include <chrono>
#include <deque>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <thread>
#include <utility>
#include <mutex>
#include <cstdlib>
#include "stdafx.h"using boost::asio::ip::tcp;
typedef std::deque<chat_message> chat_message_queue;
std::chrono::system_clock::time_point base;
class chat_session;
typedef std::shared_ptr<chat_session> chat_session_ptr;
class chat_room {
public:chat_room(boost::asio::io_service& io_service) : m_strand(io_service) {}
public:void join(chat_session_ptr);void leave(chat_session_ptr);void deliver(const chat_message&);
private:boost::asio::io_service::strand m_strand;//strand提供串行执行, 能够保证线程安全, 同时被post或dispatch的方法, 不会被并发的执行. std::set<chat_session_ptr> participants_;enum { max_recent_msgs = 100 };chat_message_queue recent_msgs_;
};class chat_session : public std::enable_shared_from_this<chat_session> {
public:chat_session(tcp::socket socket, chat_room &room): socket_(std::move(socket)),room_(room),m_strand(socket_.get_io_service()){}void start() {room_.join(shared_from_this()); //加入房间do_read_header();//读取数据包头}void deliver(const chat_message &msg){m_strand.post([this,msg]{bool write_in_progress = !write_msgs_.empty();write_msgs_.push_back(msg);if (!write_in_progress){do_write();}});}private:void do_read_header(){auto self(shared_from_this());boost::asio::async_read(socket_,boost::asio::buffer(read_msg_.data(),chat_message::header_length), //读取头数据8个字节m_strand.wrap([this,self](boost::system::error_code ec, std::size_t){if ( !ec && read_msg_.decode_header()){ do_read_body();//合法的头部的话,进行内容的读取。} else {std::cout << "player leave the room\n";room_.leave(shared_from_this());}}));}void do_read_body() {auto self(shared_from_this());boost::asio::async_read(socket_,boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),//内容的读取,async_read相当于读取缓存数据,按长度一次读取大小多少,直到读取完成。m_strand.wrap([this,self](boost::system::error_code ec, std::size_t) {if (!ec) {handleMessage();do_read_header();} else {room_.leave(shared_from_this());}}));}void handleMessage() {auto n = std::chrono::system_clock::now() - base;std::cout << "i'm in " << std::this_thread::get_id() << " time "<< std::chrono::duration_cast<std::chrono::milliseconds>(n).count() << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(3));if (read_msg_.type() == MT_BIND_NAME) {//设定昵称const BindName* bind = reinterpret_cast<const BindName*>(read_msg_.body());m_name.assign(bind->name, bind->name + bind->nameLen);} else if (read_msg_.type() == MT_CHAT_INFO) {const ChatInformation* chat = reinterpret_cast<const ChatInformation*>(read_msg_.body());m_chatInformation.assign(chat->information, chat->information + chat->infoLen);auto rinfo = buildRoomInfo();chat_message msg;msg.setMessage(MT_ROOM_INFO,&rinfo, sizeof(rinfo));room_.deliver(msg); //对当前房间发送消息} else {}}void do_write() { //发送数据auto self(shared_from_this());boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.front().data(),write_msgs_.front().length()),m_strand.wrap([this, self](boost::system::error_code ec, std::size_t) {if (!ec) {write_msgs_.pop_front();if (!write_msgs_.empty()) {do_write();}} else {room_.leave(shared_from_this());}}));}tcp::socket socket_;chat_room &room_;chat_message read_msg_;chat_message_queue write_msgs_;std::string m_name;std::string m_chatInformation;boost::asio::io_service::strand m_strand;RoomInformation buildRoomInfo() const {RoomInformation info;info.name.nameLen = m_name.size();std::memcpy(info.name.name, m_name.data(), m_name.size());info.chat.infoLen = m_chatInformation.size();std::memcpy(info.chat.information, m_chatInformation.data(),m_chatInformation.size());return info;}
};//加入房间void chat_room::join(chat_session_ptr participant) {m_strand.post([this, participant]{participants_.insert(participant);for (const auto& msg : recent_msgs_)participant->deliver(msg); //对所有端广播});}//离开房间void chat_room::leave(chat_session_ptr participant) {m_strand.post([this,participant]{participants_.erase(participant);});}void chat_room::deliver(const chat_message &msg) {m_strand.post([this, msg]{recent_msgs_.push_back(msg);while (recent_msgs_.size() > max_recent_msgs)recent_msgs_.pop_front();for (auto& participant : participants_)participant->deliver(msg);});}class chat_server {
public:chat_server(boost::asio::io_service &io_service,const tcp::endpoint &endpoint): acceptor_(io_service, endpoint), socket_(io_service), room_(io_service) {do_accept();}private:void do_accept() {acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {if (!ec) {auto session =std::make_shared<chat_session>(std::move(socket_), room_);session->start();//新客户端开始接收数据包}do_accept(); //创建新连接进行等待});}tcp::acceptor acceptor_;tcp::socket socket_;chat_room room_;
};int _tmain(int argc, char *argv[])
{try {base = std::chrono::system_clock::now();boost::asio::io_service io_service;std::list<chat_server> servers;tcp::endpoint endpoint(tcp::v4(), 9000);servers.emplace_back(io_service, endpoint);std::vector<std::thread> threadGroup;for(int i = 0; i < 5; ++i) {threadGroup.emplace_back([&io_service, i]{std::cout << i << " name is " << std::this_thread::get_id() << std::endl;io_service.run();});}io_service.run();for(auto& v : threadGroup) v.join();} catch (std::exception &e) {std::cout << "Exception: " << e.what();}return 0;
}

客户端:

//client.cpp#include "chat_message.h"
#include <asio.hpp>
#include <chrono>
#include <deque>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <thread>
#include <utility>
#include <mutex>
#include <cstdlib>
#include "stdafx.h"using boost::asio::ip::tcp;
typedef std::deque<chat_message> chat_message_queue;
class chat_client {
public:chat_client(boost::asio::io_service &io_service,tcp::resolver::iterator endpoint_iterator): io_service_(io_service), socket_(io_service) {do_connect(endpoint_iterator);}void write(const chat_message &msg) {io_service_.post([this, msg]() {bool write_in_progress = !write_msgs_.empty();write_msgs_.push_back(msg);if (!write_in_progress) {do_write();}});}void close() {io_service_.post([this]() { socket_.close(); });}private:void do_connect(tcp::resolver::iterator endpoint_iterator) {boost::asio::async_connect(socket_, endpoint_iterator,[this](boost::system::error_code ec, tcp::resolver::iterator) {if (!ec) {do_read_header();}});}void do_read_header() {boost::asio::async_read(socket_,boost::asio::buffer(read_msg_.data(), chat_message::header_length),[this](boost::system::error_code ec, std::size_t /*length*/) {if (!ec && read_msg_.decode_header()) {do_read_body();} else {socket_.close();}});}void do_read_body() {boost::asio::async_read(socket_, boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),[this](boost::system::error_code ec, std::size_t /*length*/) {if (!ec) {if (read_msg_.body_length() == sizeof(RoomInformation) &&read_msg_.type() == MT_ROOM_INFO) {const RoomInformation *info =reinterpret_cast<const RoomInformation *>(read_msg_.body());std::cout << "client: '";assert(info->name.nameLen <= sizeof(info->name.name));std::cout.write(info->name.name, info->name.nameLen);std::cout << "' says '";assert(info->chat.infoLen <= sizeof(info->chat.information));std::cout.write(info->chat.information, info->chat.infoLen);std::cout << "'\n";}do_read_header();} else {socket_.close();}});}void do_write() {boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.front().data(),write_msgs_.front().length()),[this](boost::system::error_code ec, std::size_t /*length*/) {if (!ec) {write_msgs_.pop_front();if (!write_msgs_.empty()) {do_write();}} else {socket_.close();}});}private:boost::asio::io_service &io_service_;tcp::socket socket_;chat_message read_msg_;chat_message_queue write_msgs_;
};
int _tmain(int argc, char* argv[])
{
try {boost::asio::io_service io_service;tcp::resolver resolver(io_service);boost::asio::ip::tcp::resolver::query query("localhost", "9000");auto endpoint_iterator = resolver.resolve(query);chat_client c(io_service, endpoint_iterator);std::thread t([&io_service]() { io_service.run(); });char line[chat_message::max_body_length + 1];// ctrl-dwhile (std::cin.getline(line, chat_message::max_body_length + 1)) {chat_message msg;auto type = 0;std::string input(line, line + std::strlen(line));std::string output;if(parseMessage(input, &type, output)) {msg.setMessage(type, output.data(), output.size());c.write(msg);std::cout << "write message for server " << output.size() << std::endl;}}c.close();t.join();} catch (std::exception &e) {std::cerr << "Exception: " << e.what() << "\n";}return 0;
}

运行结果:

QQ图片20181127135440.png

参考链接
http://www.cnblogs.com/zhiranok/archive/2011/09/04/boost_asio_io_service_CPP.html

Asio tcp异步例子相关推荐

  1. (C# TCP异步)客户端异常断开,服务器利用KeepAlive监测

    (C# TCP异步)客户端异常断开,服务器利用KeepAlive监测 参考文章: (1)(C# TCP异步)客户端异常断开,服务器利用KeepAlive监测 (2)https://www.cnblog ...

  2. servlet3异步 例子_异步Servlet示例

    servlet3异步 例子 Async servlet was introduced in Servlet 3. It's a great way to deal with thread starva ...

  3. Linux-C TCP简单例子

    Linux-C TCP简单例子 一.简述        记-使用TCP协议通信的简单例子. 例子1:一个客户端,一个服务端,客户端发送信息,服务端就收信息. 例子2:使用多线程实现  服务器与客户端的 ...

  4. asio boost 异步错误处理_boost::ASIO的同步方式和异步方式

    http://blog.csdn.net/zhuky/article/details/5364574 http://blog.csdn.net/zhuky/article/details/536468 ...

  5. 对Boost.Asio中异步事件循环的理解

    Boost.Asio是一个异步编程的网络框架, 核心的优势在于IO操作的异步调用. 异步调用时, 会用到boost::asio::io_context::run()函数, 这个函数表示启动一个IO的异 ...

  6. asio boost 异步错误处理_boost::asio::error的用法浅析

    boost::asio::error的用法浅析 作者:转载自:asio分享学习快乐更新时间:2009-8-2 一般而言我们创建用于接收error的类型大多声明如下: boost::system::er ...

  7. boost::asio::tcp

    同步TCP通信服务端 #include <boost/asio.hpp> #include <iostream> using namespace boost::asio; in ...

  8. asio boost 异步错误处理_boost asio 学习(五) 错误处理

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=6 5. Erro ...

  9. Boost.ASIO源码:从async_write看ASIO的异步IO逻辑

    async_write有两个对外接口: template <typename AsyncWriteStream, typename Allocator, typename WriteHandle ...

  10. 2.Java 网络编程TCP通讯例子 双向发送

    在上篇例子中,存在缺陷 只能允许Client给Server发消息,Server无法发消息给Client端 Client连接成功之后,Server就关闭了 这篇完善上篇的例子 TCP服务端 import ...

最新文章

  1. 解析python数据后用html输出
  2. golang中的执行规则
  3. php检测网址是否有效,php 检测因特网址是否有效
  4. field module的on input和on request区别
  5. macos 安装python3.8 版本_用python安装cutadapt程序
  6. POJ - 1201 Intervals(差分约束+最短路)
  7. MM看过来!教你如何打扮变成时尚达人 - 生活至上,美容至尚!
  8. 创建一个storageevent事件_谈谈StorageEvent
  9. python 数组赋值_pythonamp;numpy的赋值
  10. C++笔记-仿函数(functor)
  11. Pro Silverlight 5 in C# 分享
  12. AS 3.0 socket 通信,比较基础比较全【转载】
  13. dynamipsGUI+VMware
  14. 《Advanced .NET Debugging》 读书笔记 Listing 3-6: 使用sxe在程序载入mscorwks之后停下来载入sos...
  15. SmartDrv的前世今生——PrimoCache_2.2.0汉化
  16. 人脸识别应用在美国受禁,因噎废食还是以人为本?
  17. Linux运维工程师常见面试题(一)
  18. erp框架 saas_SaaS ERP和传统ERP的区别在哪里?
  19. 小米联合金山云发布“1KM边缘计算” 携手布局“云+边缘”新赛道
  20. 使用canvas画网格

热门文章

  1. 无法安装驱动程序此计算机上不存在,在win7中安装打印机时,如果“找不到打印机驱动程序包所需的核心驱动程序包”怎么办?...
  2. Unity塔防游戏学习(六)
  3. r语言如何计算t分布临界值_医学统计与R语言:超几何分布(Hypergeometric distribution)与Fisher精确检验...
  4. IE8 SysFader:IEXPLORE.EXE应用程序错误解决办法
  5. 手机人像摄影入门简易四步法
  6. 20162328WJH实验五网络编程与安全实验报告
  7. 传奇世界3D手游电脑版使用教程:无需安卓模拟器,tcgames完美适配
  8. linux装中文字库,对linux安装中文字体库
  9. 刨根笔记--由antd开始的jsx渲染学习路线
  10. 机器学习模型评估方法