如果你是偶然浏览到这里,请先看
源代码及例程下载地址:
命令行:svn checkout http://st-asio-wrapper.googlecode.com/svn/trunk/ st-asio-wrapper-read-only
如果从svn客户端界面上打开,则只输入http://st-asio-wrapper.googlecode.com/svn/trunk/到地址栏即可
git:https://github.com/youngwolf-project/st_asio_wrapper/,另外,我的资源里面也有下载,但不是最新的。
QQ交流群:198941541
六:开发教程(服务端)
服务端直接#include st_asio_wrapper_server.h,就可实现一个简单的服务端了,如下(还演示了一个echo服务器,所以继承st_server写了个echo_server类):
//configuration #define SERVER_PORT 9527 #define REUSE_OBJECT //use objects pool //#define FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer #define ENHANCED_STABILITY //configuration #include "st_asio_wrapper_server.h" using namespace st_asio_wrapper; #define QUIT_COMMAND "quit" #define RESTART_COMMAND "restart" #define LIST_ALL_CLIENT "list_all_client" #define LIST_STATUS "status" #define SUSPEND_COMMAND "suspend" #define RESUME_COMMAND "resume" //demonstrate how to use custom packer //in the default behavior, every st_tcp_socket has their own packer, and cause memory waste //at here, we make every echo_socket use the same global packer for memory saving //notice: do not do this for unpacker, because unpacker has member variables and can't share each other auto global_packer(boost::make_shared<packer>()); //demonstrates how to control the type of st_server_socket_base::server from template parameters class i_echo_server : public i_server { public: virtual void test() = ; }; class echo_socket : public st_server_socket_base<boost::asio::ip::tcp::socket, i_echo_server> { public: echo_socket(i_server& server_) : st_server_socket_base(server_) {inner_packer(global_packer);} public: //because we use objects pool(REUSE_OBJECT been defined), so, strictly speaking, this virtual //function must be rewrote, but we don't have member variables to initialize but invoke father's //reset() directly, so, it can be omitted, but we keep it for possibly future using virtual void reset() {st_server_socket_base::reset();} protected: virtual void on_recv_error(const error_code& ec) { //the type of st_server_base::server now can be controled by derived class(echo_socket), //which is actually i_echo_server, so, we can invoke i_echo_server::test virtual function. server.test(); st_server_socket_base::on_recv_error(ec); } //msg handling: send the original msg back(echo server) #ifndef FORCE_TO_USE_MSG_RECV_BUFFER //this virtual function doesn't exists if FORCE_TO_USE_MSG_RECV_BUFFER been defined virtual bool on_msg(msg_ctype& msg) {post_msg(msg); return false;} #endif //we should handle the msg in on_msg_handle for time-consuming task like this: virtual void on_msg_handle(msg_ctype& msg) {post_msg(msg);} //please remember that we have defined FORCE_TO_USE_MSG_RECV_BUFFER, so, st_tcp_socket will directly //use the msg recv buffer, and we need not rewrite on_msg(), which doesn't exist any more //msg handling end }; class echo_server : public st_server_base<echo_socket, st_object_pool<echo_socket>, i_echo_server> { public: echo_server(st_service_pump& service_pump_) : st_server_base(service_pump_) {} //from i_echo_server, pure virtual function, we must implement it. virtual void test() {/*puts("in echo_server::test()");*/} }; int main() { puts("type quit to end these two servers."); std::string str; st_service_pump service_pump; st_server server_(service_pump); //only need a simple server? you can directly use st_server server_.set_server_addr(SERVER_PORT + ); echo_server echo_server_(service_pump); //echo server service_pump.start_service(); while(service_pump.is_running()) { std::cin >> str; if (str == QUIT_COMMAND) service_pump.stop_service(); else if (str == RESTART_COMMAND) { service_pump.stop_service(); service_pump.start_service(); } else if (str == LIST_STATUS) { printf("normal server:\nvalid links: " size_t_format ", closed links: " size_t_format "\n", server_.size(), server_.closed_object_size()); printf("echo server:\nvalid links: " size_t_format ", closed links: " size_t_format "\n", echo_server_.size(), echo_server_.closed_object_size()); } //the following two commands demonstrate how to suspend msg dispatching, no matter recv buffer been used or not else if (str == SUSPEND_COMMAND) echo_server_.do_something_to_all(boost::bind(&echo_socket::suspend_dispatch_msg, _1, true)); else if (str == RESUME_COMMAND) echo_server_.do_something_to_all(boost::bind(&echo_socket::suspend_dispatch_msg, _1, false)); else if (str == LIST_ALL_CLIENT) { puts("clients from normal server:"); server_.list_all_object(); puts("clients from echo server:"); echo_server_.list_all_object(); } else server_.broadcast_msg(str); } return ; } //restore configuration #undef SERVER_PORT #undef REUSE_OBJECT //use objects pool //#undef FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer #undef ENHANCED_STABILITY //restore configuration
以上例子中,服务端从控制台接收数据,调用broadcast_msg广播数据;当收到数据时,会输出到控制台(st_tcp_socket实现);
其中st_server server_;这行申请了一个普通的服务端,它的功能仅仅是发送接收消息,接受连接。一般来说,就像教程一里面的客户端一样,需要从st_server_socket继承一个自己的套接字类,从st_server继承一个服务类。为此,服务端demo还演示了一个echo服务器,它会把收到的任何数据发送回去(大家可以学着做一个echo客户端,但不要echo服务端与echo客户端一同工作,否则就死循环了。
start_service开启服务,stop_service结束服务(退出时必须明确调用),is_running判断服务的运行状态;如果想修改服务端地址,则在调用start_service之前调用set_server_addr函数;
stop_service之后,可再次调用start_service开启服务;
注意:st_server的del_client一般用于服务端被动删除某个client(即在错误发生的时候,比如在st_tcp_socket的on_recv_error和on_send_error里面调用,参看st_server_socket);服务端如果想主动关闭某个client,建议调用这个client的force_close或者graceful_close(st_tcp_socket实现)函数,它们的调用最终会促使on_recv_error的调用;
st_server的close_all_client主动关闭所有client,比如服务端退出的时候(stop_service会自动调用);
重写st_server的on_accept函数,根据你自己的策略确定是否接受客户端的连接,接受返回true;
st_server的维护了一个链表(st_object_pool实现)用于保存所有的client(这样带几个好处:一、在广播消息的时候,很方便;二、可开启类似垃圾回收机制的自动清理已经关闭的连接的功能;三、可开启对象池功能),如果你想自己管理这些client,可以在on_accept里面返回false,然后把它保存在自己的容器里面,并调用start(st_server_socket实现)以便开始接受数据(只调用一次即可);
当然,你还可以在返回true的同时,自己也保存一份client(此时就不要再调用start了),这样做不会带来多少内存消耗,因为它是用智能指针包装的,复制一份只是增加一个引用计数。至于这样做有什么好处,如果你想不到,说明你不需要,当你有需求的时候,你自然而然就会知道有什么用了,我在这里只是告诉大家可以这样做,有个印象即可;
关于是重写on_msg还是on_msg_handle,请参看教程第四篇。
boost.asio包装类st_asio_wrapper开发教程(2013.12.8更新)(二)的更多相关文章
-
boost.asio包装类st_asio_wrapper开发教程(一)
一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统: 二:st_asio_w ...
-
boost.asio包装类st_asio_wrapper开发教程(2014.5.23更新)(一)-----转
一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统: 二:st_asio_w ...
-
boost.asio包装类st_asio_wrapper开发教程(转)
一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统: 二:st_asio_w ...
-
MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(二)
你开学,我放价!MyEclipse线上狂欢继续!火热开启中>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的 ...
-
Android快乐贪吃蛇游戏实战项目开发教程-03虚拟方向键(二)绘制一个三角形
该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.绘制三角形 在上一篇文章中,我们已经新建了虚拟方向键的自定义控件Direct ...
-
Kendo UI开发教程(24): 单页面应用(二) Router 类
Route类负责跟踪应用的当前状态和支持在应用的不同状态之间切换.Route通过Url的片段功能(#url)和流量器的浏览历史功能融合在一起.从而可以支持把应用的某个状态作为书签添加到浏览器中.Rou ...
-
MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(四)
MyEclipse超值折扣 限量 100 套! 立即开抢>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的形 ...
-
MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(三)
MyEclipse超值折扣 限量 100 套! 立即开抢>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的形 ...
-
MyEclipse WebSphere开发教程:安装和更新WebSphere 6.1, JAX-WS, EJB 3.0(一)
你开学,我放价!MyEclipse线上狂欢继续!火热开启中>> [MyEclipse最新版下载] MyEclipse支持Java EE技术(如JAX-WS和EJB 3.0),它们以功能包的 ...
随机推荐
-
元组tuple
tuple和list的主要区别就是tuple里的元素的是不能改变的,即tuple时immutable的 #创建tuple >>> tupa = (12 , 'ed' , 34) &g ...
-
iOS - UISwitch
前言 NS_CLASS_AVAILABLE_IOS(2_0) __TVOS_PROHIBITED @interface UISwitch : UIControl <NSCoding> @a ...
-
Sql server 日期函数和日期转换
时间函数 SQL Server Date 函数 下面的表格列出了 SQL Server 中最重要的内建日期函数: 函数 描述 GETDATE() 返回当前日期和时间 DATEPART(Type,dat ...
-
php 文件上传一例简单代码
1.程序文件 <?php //判断临时文件存放路径是否包含用户上传的文件 if(is_uploaded_file($_FILES["uploadfile"]["tm ...
-
c++设计模式-----抽象工厂模式
抽象工厂模式 要创建一组相关或者相互依赖的对象 作用:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. UML类图 抽象基类: 1)AbstractProductA.Abstrac ...
-
ReactJS的开发日常
在用React框架开发的日子里,踩的坑真不少!今天就来说说这个关于组件的周期,说的可能不是很清楚,但是也给自己留下一个踩坑的纪念,如有不妥 还望大家指点一二 Warning: setState(... ...
-
PMP和PRINCE2的价值各是什么?PRINCE2的含金量如何?PMP和prince2有什么区别?
很多学员朋友会问我同样的问题:"PMP和PRINCE2到底有什么区别?哪个含金量更高?"看来,这是所有要参加认证的朋友普遍关心的问题,我将根据自己的切身体会,从三个方面回答这个问题 ...
-
Python面向对象——重写与Super
1本文的意义 如果给已经存在的类添加新的行为,采用继承方案 如果改变已经存在类的行为,采用重写方案 2图解继承.重写与Super 注:上面代码层层关联.super()可以用到任何方法里进行调用,本文只 ...
-
spss入门
spss下载地址:http://www.ddooo.com/softdown/53379.htm
-
Linux命令学习之路——变更文档拥有者:chown
使用权限:root用户 使用方式:chown [ -cvfRh ] [ --help ] [ --version ] user[ :group ] file... 作用:该命令用于改变文档的拥有者 注 ...