`
zsxxsz
  • 浏览: 444179 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用 acl 服务器框架编写监听多个地址的服务器程序

阅读更多

      在编写服务器应用程序时,有时会有这样一种应用场景:后端的业务数据及业务逻辑相同,但希望给前端应用提供的功能范围及协议方式有些差别。如:

      场景一:希望来自于外网的客户端以只读权限访问后端数据,同时希望来自于内网的客户端可以以读/写方式访问后端数据;

      场景二:希望某个网段的客户端以 HTTP 协议访问后端业务,同时希望某个网段的客户端以私有协议方式访问后端业务。

      为了处理上面的应用场景,当然可以写多个服务器程序,每个服务器程序处理不同的协议格式和权限范围,但这势必会造成很多冗余代码,增加额外的工作量及出错可能性。acl 的服务器框架模型允许一个服务器进程同时监听多个地址,利用这一点便可以轻松解决上面的应用场景问题,同时大大减少了程序工作量及维护成本。

      下面以一个简单的例子,说明如何使用这一特性来处理不同的协议过程。

      为了简单起见,本例子使用了 使用 acl 生成向导快速创建服务器程序 文章中介绍的服务器生成向导过程来生成一个简单的 DEMO(假设让该服务器程序监听:127.0.0.1:8088 和 192.168.166.162:8080 两个地址)。假设由服务器生成向导程序生成了服务器模板类型为 master_threads (线程池模型)的程序 echo_server。然后在 echo_server 程序目录下打开  master_service.cpp 源程序,修改 函数 master_service::thread_on_accept ,master_service::thread_on_close 及 master_service::thread_on_read,内容如下:

// 当客户端连接流有数据可读/出现异常时的回调函数
bool master_service::thread_on_read(acl::socket_stream* conn)
{
	// 获得客户端连接本地的哪个监听服务地址,其中 get_local 的参数为 true 表示要求获得
	// ip:port 格式的全地址
	const char* local_addr = conn->get_local(true);
	const char* str = (const char*) conn->get_ctx();
	logger("connection from local %s on read fd %d, info: %s",
		local_addr, conn->sock_handle(), str);

	acl::string buf;
	// 从客户端读取一行数据
	if (conn->gets(buf, false) == false)
	{
		logger("get error from client %s, local addr: %s",
				conn->get_peer(true), local_addr);
		return false;  // 返回 false 通知服务器框架将连接关闭
	}

	// 回写数据
	if (conn->write(buf) == -1)
	{
		logger("write to client %s error, local addr: %s",
				conn->get_peer(true), local_addr);
		return false;
	}

	// 返回 true 通知服务器框架继续监控该客户端连接流
	return true;
}

// 当接收到一个客户端连接时的回调函数
bool master_service::thread_on_accept(acl::socket_stream* conn)
{
	// 获得客户端连接本地的哪个监听服务地址,其中 get_local 的参数为 true 表示要求获得
	// ip:port 格式的全地址
	const char* local_addr = conn->get_local(true);
	logger("connect from local addr: %s", local_addr);

	// 在此处可以根据 local_addr 的不同来区分不同的连接请求:
	if (strcmp(local_addr, "127.0.0.1:8088") == 0)
	{
		const char* str = strdup("from 127.0.0.1:8088");
		conn->set_ctx(str);
	}
	else if (strcmp(local_addr, "192.168.166.162:8080" == 0)
	{
		const char* str = strdup("from 192.168.166.162:8080");
		conn->set_ctx(str);
	}
	else
	{
		const char* str = strdup("other addr");
		conn->set_ctx(str);
	}

	// 设置客户端连接流的读写超时时间(秒)
	conn->set_rw_timeout(10);
	return true;
}

// 当客户端连接关闭前调用的回调函数
void master_service::thread_on_close(acl::socket_stream* conn)
{
	// 释放由 master_service::thread_on_accept 中分配的内存对象
	char* str = (char*) conn->get_ctx();
	if (str)
		free(str);
}

 

      上面代码逻辑很简单地演示了 acl 服务器框架支持监听多个地址的用处。为了支持不同的业务功能分流,应用可以在 thread_on_accept 阶段通过 socket_stream::set_ctx(void*) 设置不同的功能对象,在 thread_on_read 阶段通过 socket_stream::get_ctx() 取出设置的对象,通过对对象的功能判断进行业务功能分流。

       当然,还有一点不要忘记,还得需要修改该服务器的配置文件,将 master_service 的监听地址改成多个地址,如:127.0.0.1:8088, 192.168.166.162:8080  即:master_service = 127.0.0.1:8088, 192.168.166.162:8080,同时需要将 master_type 值改为 sock,即:master_type = sock。

       此外,为了在独立方式下测试服务器程序,可以打开 main.cpp 文件,将其中的 addr 的值设为 "127.0.0.1:8088, 192.168.166.162:8080" 即可。

 

       下面写一个更加实用一点的例子,可以先设计一个虚类,里面定义一个虚方法,在接收到客户端连接 (thread_on_accept) 时,根据连接地址不同来创建该虚类的子类实例(这些子类只需实现基类中的虚方法即可),在 thread_on_read 时,通过调用子类实例的虚方法来达到协议分流的目的。如下面的例子:

 

class base
{
public:
	base() {}
	virtual ~base() {}
	// 纯虚方法,需要子类实现
	virtual bool run(acl::socket_stream* conn) = 0;
};

class child1 : public base
{
public:
	child1() {}
	~child1() {}

protected:
	bool run(acl::socket_stream* conn)  // 基类虚方法实现
	{
		acl::string buf;

		// 读一行数据,但第二个参数为 true 表示希望将 \r\n 自动去掉
		if (conn->gets(buf, true) == false)
			return false;
		if (conn.format("child1: %s\r\n", buf.c_str()) == -1)
			return false;
		return true;
	}	
};

class child2 : public base
{
public:
	child2() {}
	~child2() {}

protected:
	bool run(acl::socket_stream* conn)  // 基类虚方法实现
	{
		acl::string buf;

		// 读一行数据,但第二个参数为 true 表示希望将 \r\n 自动去掉
		if (conn->gets(buf, true) == false)
			return false;
		if (conn.format("child2: %s\r\n", buf.c_str()) == -1)
			return false;
		return true;
	}	
};

/////////////////////////////////////////////////////////////////////////////////

bool master_service::thread_on_read(acl::socket_stream* conn)
{
	// 将流中参数硬转化为 base 类对象
	base* obj = (base*) conn->get_ctx();

	// 调用基类中的纯虚方法,而实际上是调用了子类的方法
	// 从而实现了协议分流
	return obj->run(conn);
}

bool master_service::thread_on_accept(acl::socket_stream* conn)
{
	const char* local_addr = conn->get_local(true);
	if (strcmp(local_addr, "127.0.0.1:8088") = 0)
	{
		base* obj = new child1();
		conn->set_ctx(obj);
		return true;
	}
	else if (strcmp(local_addr, "127.0.0.1:8080") == 0)
	{
		base* obj = new child2();
		conn->set_ctx(obj);
		return true;
	}
	else
		return false;
}

void master_service::thread_on_close(acl::socket_stream* conn)
{
	base* obj = (base*) conn->get_ctx();
	if (obj)
		delete obj;
}

 

 

参考:

acl 库下载:https://sourceforge.net/projects/acl/

svn: svn://svn.code.sf.net/p/acl/code/

github 地址:https://github.com/acl-dev/acl

QQ 群:242722074

使用 acl 生成向导快速创建服务器程序

使用 acl::master_threads 类编写多进程多线程服务器程序

acl 服务器模块的部署

      

1
1
分享到:
评论

相关推荐

    05-使用多进程完成http服务器.py

    05-使用多进程完成http服务器.py

    acl 工程是一个跨平台的网络通信库及服务器编程框架,同时提供更多的实用功能库

    acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...

    cpp-acl工程是一个跨平台的网络通信库及服务器编程框架

    acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...

    acl框架库是一个C语言网络框架库,主要包含:服务器开发框架、同步异步网络通讯、常用数据结构、进程池线程池、流式xmljson

    c语言基础 acl框架库是一个C语言网络框架库,主要包含:服务器开发框架、同步异步网络通讯、常用数据结构、进程池线程池、流式xmljson解析器、httpping应用协议等内容.zip

    Java服务器程序设计

    用java进行客户端的applet (小程序)开发的技术已广为使用,而用java进行服务器端的servlet(服务器小程序)开发则尚需揭开其神秘的面纱,本书正是基于这样的目的编写的。全书从java服务器的体系结构、开发工具和...

    acl C++跨平台库.rar

    acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...

    acl-master

    acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...

    acl-master.zip

    acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...

    acl-3.0.19

    acl 是 one advanced C/C++ library 的简称,主要包括网络通信库以及服务器框架库等功能,支持 Linux/Windows/Solaris/FreeBsd/MacOS 平台;整个 acl 项目主要包含三个函数库:lib_acl(纯C开发的基础库,主要包含...

    59-通过8021X认证服务器动态下发授权ACL典型配置举例.do编程资料cx

    59-通过8021X认证服务器动态下发授权ACL典型配置举例.docx

    acl-master_网络通信框架_aclmaster_

    acl 工程是一个跨平台的通用网络通信库,同时提供更多的其它有价值功能。通过该库,用户可以非常容易地编写支持多种模式的服务器程序、WEB 应用程序以及数据库应用程序。此外,该库还提供了 XML/JSON/MIME 编码及...

    实验:使用基本ACL限制公司网络访问.docx

    本实验使用基本ACL限制公司网络访问,三层交换机的访问策略主要是通过ACL访问控制列表对不同VLAN的IP地址段进行流量匹配控制。

    go语言开发的服务器模板,可与acl_master服务器框架深度集成.zip

    go语言开发项目go语言开发项目go语言开发项目go语言开发项目go语言开发项目 go语言开发项目go语言开发项目go语言开发项目go语言开发项目go语言开发项目 go语言开发项目go语言开发项目go语言开发项目go语言开发项目go...

    使用基本ACL限制公司网络访问.rar

    3、应用场景:使用基本ACL限制公司网络访问 4、特点:Word文档提供了实验的详细过程,包括每一步骤的操作命令和截图,并给出了实验的topo文件(包括配置信息) 5、适用人群:网络系统的建设与运维 6、使用说明:重点...

    oracle远程连接服务器出现 ORA-12170 TNS:连接超时 解决办法

    错误检查:有很多是oracle自身安装的问题,但是我这里服务器配置正常,监听正常,服务正常,远程可以ping通服务器。 这里主要是防火墙问题,解决办法: (1)关闭防火墙; (2)在防火墙中添加,orcale端口1521例外...

    acl 框架库-其他

    5、服务器框架:包括进程池模式、线程池模式、非阻塞模式、UDP通信模式及触发器模式 6、事件引擎:支持 select、poll(for unix)、epoll(for linux)、kqueue(for bsd)、devpoll(for solaris)、iocp(for win32)、win32...

    acl_cpp:用于win32 / linux,服务器框架,HttpServlet的功能强大的c ++库-开源

    acl_cpp(已包含在acl项目中:https://sourceforge.net/projects/acl/,请从acl项目url下载)是acl的c ++包装库,并且acl_cpp比acl具有更多有用的功能,例如例如流式mime解析,处理程序套接字支持以及db(mysql和...

    交换机ACL在WWW服务器安全防护中的应用

    使用动态端口固定化原则和动态管理IP固定化原则,并据此配置服务器接入交换机ACL (访问控制列表),并将针对于每个服务器的ACL应用于服务器连接的交换机端口,对服务器进行点防护.在服务器防火墙规则禁用的情况下,...

    动态ACL动态ACL动态ACL

    动态ACL 动态ACL 动态ACL 动态ACL 动态ACL

Global site tag (gtag.js) - Google Analytics