一、前言
这里注意的是,定义了一个tag="KDS",目的是为了检查收到的数据包是否有效,每一个数据包前3个字节不为“KDS”,那么就认为是非法的请求包,你也可以定义tag等于其它字符串,只要按协议发包就正常,当然这是比较简单的数据包检查方法了。比较严谨的方法是双方使用哈希算法来检查的,怎么做,这里先不做详解。
boost asio可算是一个简单易用,功能又强大可跨平台的C++通讯库,效率也表现的不错,linux环境是epoll实现的,而windows环境是iocp实现的。而tcp通讯是项目当中经常用到通讯方式之一,实现的方法有各式各样,因此总结一套适用于自己项目的方法是很有必要,很可能下一个项目直接套上去就可以用了。
二、实现思路 1.通讯包数据结构
Tag:检查数据包是否合法,具体会在下面讲解;
Length:描述Body的长度;
Command:表示数据包的类型,0表示心跳包(长连接需要心跳来检测连接是否正常),1表示注册包(客户端连接上服务器之后要将相关信息注册给服务器),2表示业务消息包;
business_type:业务消息包类型,服务器会根据业务消息包类型将数据路由到对应的客户端(客户端是有业务类型分类的);
app_id:客户端唯一标识符;
Data:消息数据;
2.连接对象客户端连接上服务器之后,双方都会产生一个socket连接对象,通过这个对象可以收发数据,因此我定义为socket_session。
//socket_session.h
- #pragma once
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using boost::asio::ip::tcp;
- namespace firebird{
- enum command{ heartbeat = 0, regist, normal};
- const std::string tag = "KDS";
- class FIREBIRD_DECL socket_session;
- typedef boost::shared_ptr socket_session_ptr;
- class FIREBIRD_DECL socket_session:
- public boost::enable_shared_from_this,
- private boost::noncopyable
- {
- public:
- typedef boost::function close_callback;
- typedef boost::function read_data_callback;
- socket_session(boost::asio::io_service& io_service);
- ~socket_session(void);
- DWORD id() { return m_id; }
- WORD get_business_type(){ return m_business_type; }
- void set_business_type(WORD type) { m_business_type = type; }
- DWORD get_app_id(){ return m_app_id; }
- void set_app_id(DWORD app_id) { m_app_id = app_id; }
- std::string& get_remote_addr() { return m_name; }
- void set_remote_addr(std::string& name) { m_name = name; }
- tcp::socket& socket() { return m_socket; }
- void installCloseCallBack(close_callback cb){ close_cb = cb; }
- void installReadDataCallBack(read_data_callback cb) { read_data_cb = cb; }
- void start();
- void close();
- void async_write(const std::string& sMsg);
- void async_write(message& msg);
- bool is_timeout();
- void set_op_time(){std::time(&m_last_op_time);}
- private:
- static boost::detail::atomic_count m_last_id;
- DWORD m_id;
- WORD m_business_type;
- DWORD m_app_id;
- std::string m_name;
- boost::array sHeader;
- std::string sBody;
- tcp::socket m_socket;
- boost::asio::io_service& m_io_service;
- std::time_t m_last_op_time;
- close_callback close_cb;
- read_data_callback read_data_cb;
- //发送消息
- void handle_write(const boost::system::error_code& e,
- std::size_t bytes_transferred, std::string* pmsg);
- //读消息头
- void handle_read_header(const boost::system::error_code& error);
- //读消息体
- void handle_read_body(const boost::system::error_code& error);
- void handle_close();
- };
- }
//socket_session.cpp
- #include "socket_session.h"
- namespace firebird{
- boost::detail::atomic_count socket_session::m_last_id(0);
- socket_session::socket_session(boost::asio::io_service& io_srv)
- :m_io_service(io_srv), m_socket(io_srv),
- m_business_type(0), m_app_id(0)
- {
- m_id = ++socket_session::m_last_id;
- }
- socket_session::~socket_session(void)
- {
- m_socket.close();
- }
- void socket_session::start()
- {
- m_socket.set_option(boost::asio::ip::tcp::acceptor::linger(true, 0));
- m_socket.set_option(boost::asio::socket_base::keep_alive(true));
- std::time(&m_last_op_time);
- const boost::system::error_code error;
- handle_read_header(error);
- }
- void socket_session::handle_close()
- {
- try{
- m_socket.close();
- close_cb(shared_from_this());
- }
- catch(std::exception& e)
- {
- LOG4CXX_ERROR(firebird_log, KDS_CODE_INFO
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?
立即登录/注册


微信扫码登录