简化asio的聊天代码 去除ROOM的设计

所有连接客户端均在同一个ROOM下

/**************************************************************
技术博客
http://www.cnblogs.com/itdef/
 
技术交流群
群号码:324164944
 
欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
**************************************************************/
 

chat message 使用boost自带示例的头文件

#pragma once

#include <cstdio>
#include <cstdlib>
#include <cstring> class chat_message
{
public:
enum { header_length = 4 };
enum { max_body_length = 512 }; chat_message():
body_length_(0)
{} const char* data()const
{
return data_;
} char* data()
{
return data_;
} size_t length()const
{
return header_length + body_length_;
} const char* body()const
{
return data_ + header_length;
}
char* body()
{
return data_ + header_length;
}
size_t body_length()const
{
return body_length_;
} void body_length(size_t new_length)
{
body_length_ = new_length;
if (body_length_ > max_body_length)
body_length_ = max_body_length;
} bool decode_header()
{
using namespace std;
char header[header_length + 1] = "";
strncat(header, data_, header_length);
body_length_ = atoi(header);
if (body_length_ > max_body_length)
{
body_length_ = 0;
return false;
}
return true;
} void encode_header()
{
using namespace std;
char header[header_length + 1] = "";
sprintf(header,"%4d",static_cast<int>(body_length_));
memcpy(data_,header,header_length);
} private:
char data_[header_length + max_body_length];
size_t body_length_;
};

  

// MyChat.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <set>
#include <iostream>
#include "chat_message.h" using namespace boost::asio::ip; const int defaultPort = 8899; class chat_session;
typedef boost::shared_ptr<chat_session> chat_session_ptr; class chat_session :
public boost::enable_shared_from_this<chat_session>
{
public:
chat_session(boost::asio::io_service& io_service, std::set<chat_session_ptr>& sessionList)
: socket_(io_service), sessionList_(sessionList)
{
} ~chat_session() { std::cout << "~chat_session()" << std::endl; }
tcp::socket& socket()
{
return socket_;
} void start()
{
sessionList_.insert(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(
&chat_session::handle_read_header, shared_from_this(),
boost::asio::placeholders::error));
} void handle_read_header(const boost::system::error_code& error)
{
if (!error && read_msg_.decode_header() )
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
boost::bind(&chat_session::handle_read_body, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
// occur error,delete from list
sessionList_.erase(shared_from_this());
socket_.shutdown(tcp::socket::shutdown_both);
socket_.close();
return;
}
} void handle_read_body(const boost::system::error_code& error)
{
if (!error)
{
std::cout << read_msg_.data() << std::endl;
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(&chat_session::handle_read_header, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
// occur error,delete from list
sessionList_.erase(shared_from_this());
socket_.shutdown(tcp::socket::shutdown_both);
socket_.close();
return;
} } private:
char recvbuf[5];
tcp::socket socket_;
chat_message read_msg_;
std::set<chat_session_ptr>& sessionList_;
}; typedef boost::shared_ptr<chat_session> chat_session_ptr; class chat_server
{
public:
chat_server(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint)
: io_service_(io_service),
acceptor_(io_service, endpoint)
{
start_accept();
} void start_accept()
{
chat_session_ptr new_session(new chat_session(io_service_, sessionList_));
acceptor_.async_accept(new_session->socket(),
boost::bind(&chat_server::handle_accept, this, new_session,
boost::asio::placeholders::error));
} void handle_accept(chat_session_ptr session,
const boost::system::error_code& error)
{
if (!error)
{
session->start();
} start_accept();
}
private:
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
std::set<chat_session_ptr> sessionList_;
}; typedef boost::shared_ptr<chat_server> chat_server_ptr; int main()
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v4(), defaultPort);
chat_server chatServer(io_service, endpoint); io_service.run();
return 0;
}

  测试客户端 chat_message头文件公用

// MyChatCLient.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include "chat_message.h"
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp> using boost::asio::ip::tcp; #define testString "this is a test string......." class chat_client:
public boost::enable_shared_from_this<chat_client>
{
public:
chat_client(boost::asio::io_service& io_service,
tcp::resolver::iterator endpoint_iterator)
: io_service_(io_service), endpoint_iterator_(endpoint_iterator),
socket_(io_service)
{ } void do_close()
{
socket_.close();
} void Start()
{
boost::asio::async_connect(socket_, endpoint_iterator_,
boost::bind(&chat_client::handle_connect, shared_from_this(),
boost::asio::placeholders::error));
} private:
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
chat_message write_msg_;
write_msg_.body_length(strlen(testString) + 1);
memcpy(write_msg_.body(), testString, write_msg_.body_length());
write_msg_.encode_header(); boost::asio::async_write(socket_,
boost::asio::buffer(write_msg_.data(),
write_msg_.length()),
boost::bind(&chat_client::handle_write, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
do_close();
}
}
void handle_connect(const boost::system::error_code& error)
{
if (!error)
{
chat_message write_msg_;
write_msg_.body_length(strlen(testString)+1);
memcpy(write_msg_.body(), testString, write_msg_.body_length());
write_msg_.encode_header(); boost::asio::async_write(socket_,
boost::asio::buffer(write_msg_.data(),
write_msg_.length()),
boost::bind(&chat_client::handle_write, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
do_close();
}
} private:
boost::asio::io_service& io_service_;
tcp::socket socket_;
chat_message write_msg_;
tcp::resolver::iterator endpoint_iterator_;
};
typedef boost::shared_ptr<chat_client> chat_client_ptr; int main()
{
boost::asio::io_service io_service; tcp::resolver resolver(io_service);
tcp::resolver::query query("127.0.0.1", "8899");
tcp::resolver::iterator iterator = resolver.resolve(query);
for (int i = 0; i < 100; i++)
{
chat_client_ptr a(new chat_client(io_service, iterator));
a->Start();
} io_service.run();
return 0;
}

  运行效果图

关闭客户端后

boost asio 网络聊天 代码修改学习的更多相关文章

  1. boost asio 学习(九) boost::asio 网络封装

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=10 9. A ...

  2. Boost.Asio 网络编程([译]Boost.Asio基本原理)

    转自:https://m.w3cschool.cn/nlzbw/nlzbw-3vs825ya.html Boost.Asio基本原理 这一章涵盖了使用Boost.Asio时必须知道的一些事情.我们也将 ...

  3. 改进基于Boost.Asio的聊天服务

    Boost.Asio是个非常易用的C++异步网络库,官方文档中一个示例是聊天服务,分为chat_message.chat_client.chat_server三个部分.chat_server的启动代码 ...

  4. boost Asio网络编程简介

    :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...

  5. boost::asio网络传输错误码的一些实验结果(recv error_code)

    错误码很重要,可以由此判断网络连接到底发生了神马事情,从而驱动高层逻辑的行为.只有笼统的错误码判断的网络层是不够规范的,鄙人觉得有些错误码还是需要在网络层就区分开的,特此记录一些当前实验的错误码以及发 ...

  6. boost asio 一个聊天的基本框架

    示例代码 #include "Util.h" #include "MyAsio.h" #include "TcpConnectionManager.h ...

  7. boost::asio译文

        Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENS ...

  8. Boost.Asio技术文档

    Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENSE_1_ ...

  9. boost::asio::io_service类

    大部分使用Boost.Asio编写的代码都会使用几个io_service的实例.io_service是这个库里面最重要的类:它负责和操作系统打交道,等待所有异步操作的结束,然后为每一个异步操作调用其完 ...

随机推荐

  1. lavarel mongo 操作

    本人使用环境   Ubuntu 18.04 LTS php7.2 lavarel5.5 mongodb的安装 mongodb 服务的安装   这个链接中有最全面最新的安装文档 https://docs ...

  2. 关于分布式uuid的一点设想

    在一次公开课上,听别人讲过全局分布式uuid的设计,听过twitter的snowflake的设计.也听过,如果使用单独的计数器服务,不可能每次都保存当前计数器到文本,自己想到应该可以每隔一些数,例如1 ...

  3. Vue 爬坑之路(一)—— 使用 vue-cli 搭建项目

    vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli vue ...

  4. python:带参数的装饰器,函数的有用信息

    一.带参数的装饰器,函数的有用信息 def func1(): '''此函数的功能是完成的登陆的功能 return: 返回值是登陆成功与否(true,false) ''' print(333) func ...

  5. mysql Mac篇

    默认为mysql下载和安装完毕,安装为默认安装 下载地址:https://dev.mysql.com/downloads/file/?id=473576 1.启动mysql sudo /usr/loc ...

  6. css实现垂直居中的方法整理

    1.表格布局法.(利用表格的显示模式)需要用到一些冗余的 HTML 元素,因此这里不多介绍. 2.行内块法.也不作讨论,因为在我看来这种方法 hack 的味道很浓. 如果你有兴趣,可以去看看 Chri ...

  7. CountDownLatch两种用法

    1.当前线程等待其他线程执行完毕后在执行. 2.模拟高并发场景. 在多线程编程里,CountDownLatch是一个很好的计数器工具. 常用的两个方法: 1.计数器减一 public void cou ...

  8. easy ui 关闭选项卡

    var tab = window.parent.getCurrentTab(); var tabs = window.parent.getTabs(); var index = tabs.tabs(& ...

  9. 发送Http

    /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1& ...

  10. 判断是否某App

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name= ...