acl_cpp 非梗阻模块的IPC通信机制

教导的本质恰是在于降服本身身上的动物本能和成长人所特有的全部个性。  
在 acl_cpp 的非梗阻框架的设计中,充沛哄骗了操纵体系平台的高并发机制,同时简化了异步编程的过程。然则,并不是所有的操纵都长短梗阻的,实际的法度应用中存在着多量的梗阻式行动,acl_cpp 的非梗阻框架中设计了一种经由过程 ipc 模式使梗阻式函数与 acl_cpp 的非梗阻过程相连络的机制。便是说,在 acl_cpp 的主线程长短梗阻的,而把梗阻过程放在零丁的一个线程中运行,当梗阻线程运算完毕,会以 ipc 体式格式通知主线程运行成果,如许就达到了梗阻与非梗阻相连络的模式。下图显现了 ipc 类的持续关系:

护士必必要有同情心和一双愿意工作的手。



   以上图中有两个类与 ipc 相干:ipc_server 及 ipc_client,此中 ipc_server 其实用于与异步流相干,而ipc_client 与客户端连接流相干。在 ipc_server 类中有一个 open 函数用来打开本地地址,还有三个虚函数便于子类进行相干操纵:

   1)on_accept:当流获得一个客户端连接时回调此函数,将获得的客户端撒播递给子类对象;

   2)on_open:当用户调用 ipc_server::open 函数,且某一办事地址成功时经由过程该函数将实际的地址传递给子类对象(因为在调用 open(addr) 时,addr 一般仅指定 IP 地址,同时将 端口赋 0 以便于操纵体系主动分派本地端标语,所以经由过程 on_open 便可以将实际的 端口传递给子类对象);

   3)on_close:当流封闭时调用此函数通知子类对象。



   相对于 ipc_server 类,则 ipc_client 的接口就显得斗劲多,首要的函数如下:

   1)open:共有四个 open 重载函数用连接流办事地址,此中两个是同步流体式格式,两个是异步流体式格式,一般同步建树的流用在梗阻式线程中,异步建树的流用在非梗阻线程中;

   2)send_message:一般用来向非梗阻主线程发送消息;

   3)on_message:异步接管到梗阻线程发来的消息的回调函数;

   4)append_message:添加异步流想要接管的消息号。

   ipc_client 类斗劲特别,其充当着双重身份:1)作为客户端连接流连接流的办事地址,一般用在梗阻式线程中;2)作为流接管到来自于客户端流的连接恳求而创建的与之对应的办事端异步流,一般用在非梗阻线程中。



   下面以一个具体的实例来申明若是应用 ipc_server 及 ipc_client 两个类:



#include "lib_acl.h"
#include <iostream>
#include "aio_handle.hpp"
#include "ipc_server.hpp"
#include "ipc_client.hpp"

using namespace acl;

#define MSG_REQ		1
#define MSG_RES		2
#define MSG_STOP		3

// 消息客户端连接类定义
class test_client1 : public ipc_client
{
public:
	test_client1()
	{

	}

	~test_client1()
	{

	}

	// 连接消息办事端地址成功后的回调函数
	virtual void on_open()
	{
		// 添加消息回调对象,接管消息办事器的
		// 此类消息
		this->append_message(MSG_RES);

		// 向消息办事器发送恳求消息
		this->send_message(MSG_REQ, NULL, 0);

		// 异步守候来自于消息办事器的消息
		wait();
	}

	// 流封闭时的回调函数
	virtual void on_close()
	{
		 this;
	}

	// 接管到消息办事器的消息时的回调函数,此中的消息号由
	// append_message 进行注册
	virtual void on_message(int nMsg, void*, int)
	{
		std::cout << "test_client1 on message:" << nMsg << std::endl;

		// 向消息办事器发送消息,通知消息办事器停止
		this->send_message(MSG_STOP, NULL, 0);

		// 删除在 on_open 中注册的消息号
		this->_message(MSG_RES);

		// 本异步消息过程停止运行
		this->get_handle().stop();

		// 封闭本异步流对象
		this->close();
	}
protected:
private:
};

// 消息客户端处理惩罚过程

static bool client_main(aio_handle* handle, const char* addr)
{
	// 创建消息连接
	ipc_client* ipc = new test_client1();
	
	// 连接消息办事器
	if (ipc->open(handle, addr, 0) == false)
	{
		std::cout << "open " << addr << " error!" << std::endl;
		 ipc;
		return (false);
	}

	return (true);
}

// 子线程的进口函数
static void* thread_callback(void *ctx)
{
	const char* addr = (const char*) ctx;
	aio_handle handle;

	if (client_main(&handle, addr) == false)
	{
		handle.check();
		return (NULL);
	}

	// 子线程的异步消息轮回
	while (true)
	{
		if (handle.check() == false)
			break;
	}

	// 最后清理一些可能未封闭的流连接
	handle.check();

	return (NULL);
}

// 消息办事器接管到的客户端连接流类定义
class test_client2 : public ipc_client
{
public:
	test_client2()
	{

	}

	~test_client2()
	{

	}

	virtual void on_close()
	{
		 this;
	}

	// 接管到消息客户端发来消息的回调函数
	virtual void on_message(int nMsg, void*, int)
	{
		std::cout << "test_client2 on message:" << nMsg << std::endl;

		// 若是收到消息客户端请求退出的消息,则主线程了退出
		if (nMsg == MSG_STOP)
		{
			this->close();

			// 通知主线程的非梗阻引擎封闭
			this->get_handle().stop();
		}
		else
			// 回应客户端消息
			this->send_message(MSG_RES, NULL, 0);
	}
protected:
private:
};

// 主线程的消息办事器 ipc 办事类定义
class test_server : public ipc_server
{
public:
	test_server()
	{

	}

	~test_server()
	{

	}

	// 消息办事器接管到消息客户端连接时的回调函数	
	void on_accept(aio_socket_stream* client)
	{
		// 创建 ipc 连接对象
		ipc_client* ipc = new test_client2();

		// 打开异步IPC过程
		ipc->open(client);

		// 添加消息回调对象
		ipc->append_message(MSG_REQ);
		ipc->append_message(MSG_STOP);
		ipc->wait();
	}
protected:
private:
};

static void usage(const char* procname)
{
	printf("usage: %s -h[help] -t[use thread]
", procname);
}

int main(int argc, char* argv[])
{
	int   ch;
	bool  use_thread = false;

	while ((ch = getopt(argc, argv, "ht")) > 0)
	{
		switch (ch)
		{
		case ""h"":
			usage(argv[0]);
			return (0);
		case ""t"":
			use_thread = true;
			break;
		default:
			break;
		}
	}

	acl_init();

	aio_handle handle;

	ipc_server* server = new test_server();

	// 使消息办事器 127.0.0.1 的地址
	if (server->open(&handle, "127.0.0.1:0") == false)
	{
		 server;
		std::cout << "open server error!" << std::endl;
		getchar();
		return (1);
	}

	char  addr[256];
#ifdef WIN32
	_snprintf(addr, sizeof(addr), "%s", server->get_addr());
#else
	snprintf(addr, sizeof(addr), "%s", server->get_addr());
#endif

	if (use_thread)
	{
		// 使消息客户端在子线程中零丁运行
		acl_pthread_t tid;
		acl_pthread_create(&tid, NULL, thread_callback, addr);
	}

	// 因为消息客户端也长短梗阻过程,所以也可以与消息办事器
	// 在同一线程中运行
	else
		client_main(&handle, addr);

	// 主线程的消息轮回过程
	while (true)
	{
		if (handle.check() == false)
		{
			std::cout << "stop now!" << std::endl;
			break;
		}
	}

	 server;
	handle.check();  // 清理一些可能未封闭的异步流对象

	std::cout << "server stopped!" << std::endl;
	getchar();
	return (0);
}

以上例子相对简单,其显现的消息办事器与消息客户端均长短梗阻过程,其实将上方的异步消息客户端稍微一改便可以改成同步消息客户端了,批改项目组如下:


class test_client3 : public ipc_client
{
public:
	test_client3()
	{

	}

	~test_client3()
	{

	}

	virtual void on_open()
	{
		// 添加消息回调对象
		this->append_message(MSG_RES);

		// 向消息办事器发送恳求消息
		this->send_message(MSG_REQ, NULL, 0);

		// 同步守候消息
		wait();
	}

	virtual void on_close()
	{
		 this;
	}

	virtual void on_message(int nMsg, void*, int)
	{
		std::cout << "test_client3 on message:" << nMsg << std::endl;
		this->send_message(MSG_STOP, NULL, 0);
		this->_message(MSG_RES);
		this->close();
	}
protected:
private:
};

// 子线程处理惩罚过程

static bool client_main(const char* addr)
{
	// 创建消息客户端对象
	ipc_client* ipc = new test_client3();
	
	// 同步体式格式连接消息办事器
	if (ipc->open(addr, 0) == false)
	{
		std::cout << "open " << addr << " error!" << std::endl;
		 ipc;  // 当消息客户端未成功创建时须要在此处删除对象
		return (false);
	}

	return (true);
}

static void* thread_callback(void *ctx)
{
	const char* addr = (const char*) ctx;

	if (client_main(addr) == false)
		return (NULL);
	return (NULL);
}

对比 test_client1 与 test_client_3 两个消息客户端,可以发明二者差别并不太大,关键在于调用 open 时是采取了异步还是同步连接消息办事器,其决意了消息客户端是异步的还是同步的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值