2、python进程间通信方案设计

简介: 解决进程间各功能类之间的通信问题。

3.进程间通信方案

3.1方案一:类UDP通信

3.1.1设计思路

由于工具将界面和任务处理进行了分离,因此,工具的整体框架可以看成是由客户端和服务器组成,客户端发送请求,服务器响应请求并返回结果。

客户端即界面,用户在界面上操作,并最终在界面上得到操作的结果。界面由主界面和子界面组成,每个界面是一类相同任务类型的集合,如Snmp报文测试界面可以执行向设备发送snmp报文的任务,连接类界面则实现了SSHNetconf等登陆设备的方式。

服务器则由任务分发模块和任务处理模块组成,任务分发模块将请求的任务分发至对应的任务处理模块进行处理。任务处理模块的功能是执行具体的任务请求,每个模块均是一类任务类型的集合,简单来看任务处理模块和界面之间可以存在一一对应的关系,如Snmp报文测试界面存在对应的Snmp报文任务模块,连接类界面存在对应的连接类任务模块。不同的是,一类界面可能同时打开多个子界面,如连接类子界面0、连接类子界面1,而任务处理模块则只存在一个实例,处理所有子界面的任务请求。需要注意的是,实际界面和任务模块之间并不是绑定的关系,即界面的请求根据其任务类型,可以发送给多个不同的任务模块。所以服务器的任务模块需要包含所有界面中的任务请求处理程序,如果服务器收到未知的任务请求,会返回任务未定义错误信息。

image.png

1 界面和服务器

综上所诉,进程间通信需要解决的问题是,将某一界面的任务请求数据(任务请求代码和附加数据)发送至对应的任务处理模块,并且将任务处理结果返回至该界面。为了解决该问题,采用UDP通信的思想,给每个界面和任务处理模块分配一个IP,数据封装在报文中,报文包含源IP地址和目的IP地址,转发模块根据IP转发报文,达到通信的目的。

image.png

2 数据传输问题

3.1.2详细设计

image.png

1 通信设计图

一、网络结构

1、硬件结构:

(1)  硬件结构由PipeQueue组成,所有的报文均是生产者写入Pipe或者Queue,由消费者从Pipe或者Queue中读取报文,以达到报文在进程间和线程间转发的目的;

2、转发模块:

(1)  转发模块主要负责定义数据包格式和地址格式;

(2)  解析接收到的报文的地址,选择路由进行转发;

3、应用层:

(1)  发送数据的接口;

二、报文结构

1、报文由首部和数据两部分组成,首部的主要目的是标记路由信息,数据的主要目的是携带任务执行所需要的必要信息。

image.png

2 报文结构

2、如下图,首部包含源IP、目的IP、请求任务类型代码和报文编号。

image.png

3 报文首部

(1)IP:发送报文模块的IP地址;

(2)目的IP:报文的接收模块的IP地址;

(3)请求任务类型代码:任务类型大类,指定了由哪个任务处理模块处理本次任务请求,如指定连接类任务模块响应任务请求;

(4)报文编号:每条报文的唯一标识,可根据报文编号对应发送的报文和任务处理后的响应报文,报文编号由应用层自动生成;

3、数据部分由下图所示五部分组成:

image.png

4 数据结构

(1)请求任务具体类型:指定了任务处理模块中的具体任务,如连接类模块中的建立SSH连接任务;

(2)附加数据:执行任务所需的数据,如建立SSH连接任务需要设备IP、用户名和密码等数据,附加数据的数据格式由各个任务自行定义,无统一规定;

(3)任务是否成功标识:此部分由任务处理模块在响应报文中添加,标记了此次任务请求是否执行成功;

(4)任务错误信息:此部分由任务处理模块在响应报文中添加,记录任务执行过程中出现的错误信息;

(5)任务结果附加信息:此部分由任务处理模块在响应报文中添加,记录任务执行的具体结果数据,如请求向设备发送命令任务得到的设备回显信息;

4、Python实现的报文是字典类型,如下所示:

package = {

   'source_id': source_buffer_id,  

   'destination_id': destination_buffer_id,  

   'task_id': task_id,

   'msg_id': msg_id,

   'data': data

}

data = {

   'task_type': task_type0,

   'append_data': [],

'task_success': True/False,

task_type0: None,

'error_msg': error_msg

}

与报文的对应关系为:

image.png

image.png

图5 Python实现与报文的对应关系

三、程序设计

1、IP格式:

(1)  IP由两位数字组成,数字之间用_分割,如1_32

(2)  IP在局域网中是唯一的,跨局域网可能存在相同的IP

2、IP分配:

(1)  首先要确定哪些对象需要分配IP,本工具对于具体的功能类分配唯一的IP地址,功能类是一类功能实体的集合,在程序中表现为类,如各个子界面、任务处理模块;

(2)  每一类的功能模块有全局唯一的代码,作为IP的首位,此代码也是task_id的首位;

image.png

图6功能模块代码

(3)  一类界面的多个子界面IP的首位是相同的,比如两个连接类子界面的IP分别为5_05_1,即可以通过IP的首位确定是哪一类的功能模块;

(4)  将每个进程看做是一个局域网,进程启动时会分配到一个局域网IP。数据如需发送至其他进程,则报文中的目的IP需要包含局域网的IP,否则默认报文在当前局域网(进程)中转发;

(5)  子进程的IP由主进程在创建子进程时生成;

(6)  各个功能模块的IP由主线程在创建功能模块时生成;

3、路由学习:

(1)  工具的路由是静态的,主进程在创建子进程时,会将所有进程的IP信息都发送给子进程;

(2)  进程内,各个功能模块的代码存储在主线程中,供转发线程查询;

4、转发规则:

(1)  报文由报文转发线程进行转发,每个进程中只有一个转发线程,即界面程序设计方案2中的监听线程;

(2)  转发线程在接收到报文之后,首先分析目的地址:

①   目的地址只含有一个IP地址时,如果此IP地址与当前进程的IP地址相同,则分析task_id,根据task_id确定任务处理模块;

②   目的地址只含有一个IP地址时,如果此IP地址与当前进程的IP地址不同,则寻找路由进行转发;

③   目的地址包含多个IP地址时,提取首位IP,如果首位IP与当前进程IP相同,则根据第二个IP进行转发,且转发前,删除首位IP,如8_0_9_0修改为9_0

④   目的地址包含多个IP地址时,如果首位IP与当前进程IP不同,则根据首位IP进行转发;

⑤   如果找不到转发路由,则返回功能未定义错误;

(3)  如果报文需要转发到其他进程,且源IP的首位IP不是当前进程的IP,则将在'source_id'的头部加入当前进程的IP,标记报文经过了当前进程,如9_0转发后为8_0_9_0

(4)  一个报文支持多目的地址转发,所有目的地址以list的形式存放在destination_id对应的值中;

(5)  功能处理模块接收到报文之后,如果报文中的task_type未定义处理方法,则返回功能未定义错误,如果task_type已定义,则返回处理后的结果;

(6)  功能处理模块处理完请求的任务后,将接收到报文中的source_iddestination_id交换再交由转发线程转发;

(7)  当程序包含多个子进程时,子进程间的通信经由主进程实现,即子进程0的报文先发送至主进程,再由主进程转发至子进程1,目的是不需要建设过多的物理线路,简化程序设计;

(8)  传输大数据时,数据先存放在文件中,报文中只发送文件的目录地址;

5、进程间转发:

image.png

图7进程间转发

(1)  某个功能模块将待发送的数据通过报文生成模块生成原始报文,如Trap界面(集成在了监听界面)发送请求启动Trap监听的报文,

其中:

9_0:监听界面的IP

6_0:表示报文的目的地是任务中心进程:

1_2023...:请求由Trap功能模块执行任务;

0:执行的具体任务代码为0,即'start_listening'

{'source_id': '9_0', 'destination_id': '6_0', 'task_id': '1_20230321105253598910', 'msg_id': '20230321105253598564', 'data': {'task_type': 0, 'append_data': [{'port': '160', 'ipv4': True, 'ipv6': True}]}}

(2)  主进程的转发线程在接收到报文之后,由于需要转发的其他进程,在'source_id'的头部加入当前进程的IP,如上述报文处理后被转发:

{'source_id': '8_0_9_0', 'destination_id': '6_0', 'task_id': '1_20230321105253598910', 'msg_id': '20230321105253598564', 'data': {'task_type': 0, 'append_data': [{'port': '160', 'ipv4': True, 'ipv6': True}]}}

(3)  子进程接收到报文后,检查destination_id,如果目的地址就是当前进程,无下一跳地址,则分析task_id,根据task_id首位确定报文请求的服务应该发送至哪个功能模块进行处理,如上述报文将转发至Trap模块。如果功能模块未定义,则子进程返回未定义错误;

(4)  功能模块接收到报文之后,提取task_type,并在定义的服务列表中寻找该task_type,如果task_type已定义处理方法,则调用方法执行任务,处理完成后返回处理结果,如果task_type未定义,则返回未定义错误。上述报文在处理完成后返回的报文如下:

{'source_id': '6_0', 'destination_id': '8_0_9_0', 'task_id': '1_20230321105253598910', 'msg_id': '20230321105253598564', 'data': {'task_type': 0, 'append_data': [{'port': '160', 'ipv4': True, 'ipv6': True}], 'task_success': True, 'error_msg': ''}}

(5)  子进程转发线程将功能模块处理完成后的报文根据目的地址进行转发,如上述报文经过子进程转发后为:

{'source_id': '6_0', 'destination_id': '8_0_9_0', 'task_id': '1_20230321105253598910', 'msg_id': '20230321105253598564', 'data': {'task_type': 0, 'append_data': [{'port': '160', 'ipv4': True, 'ipv6': True}], 'task_success': True, 'error_msg': ''}}

(6)  主进程在接收到报文后,根据转发规则转发报文,如上述报文经过转发后为:

{'source_id': '8_0_6_0', 'destination_id': '9_0', 'task_id': '1_20230321105253598910', 'msg_id': '20230321105253598564', 'data': {'task_type': 0, 'append_data': [{'port': '160', 'ipv4': True, 'ipv6': True}], 'task_success': True, 'error_msg': ''}}

目的地址为9_0,报文将会转发到IP9_0的监听界面。

(7)  最终,处理后的报文返回到发起服务请求的界面,完成了从发起服务请求,到处理服务请求,最后返回服务请求结果的完整流程。

6、进程内转发:

image.png

图8进程内转发

进程内转发与进程间转发的差异在于报文的目的地址首位IP不指向其他进程的IP,转发线程在接收到报文后,寻找路由进行转发。其他过程与进程间转发一致。

7、主动上报:

image.png

图9事件上报

功能模块在响应任务返回结果之后,后台可能依然会存在任务执行线程,该线程会记录任务对应的源IP等信息。如果线程在执行任务过程中出现异常事件,线程会将该事件根据记录的源IP上报给请求服务的模块。如trap模块在后台持续执行监听任务过程中,如果遇到异常退出监听的事件,监听任务线程会将事件上报给监听界面,告知用户后台的任务运行情况。

3.1.3方案有效性

此方案能够实现进程内和跨进程的通信功能,且不存在丢包的情况。

3.1.4程序示例

https://github.com/AlvinsFish/UiExample

 

目录
相关文章
|
4天前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
15 3
|
23天前
|
负载均衡 Java 调度
探索Python的并发编程:线程与进程的比较与应用
本文旨在深入探讨Python中的并发编程,重点比较线程与进程的异同、适用场景及实现方法。通过分析GIL对线程并发的影响,以及进程间通信的成本,我们将揭示何时选择线程或进程更为合理。同时,文章将提供实用的代码示例,帮助读者更好地理解并运用这些概念,以提升多任务处理的效率和性能。
45 3
|
1天前
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
7 0
|
1月前
|
消息中间件 安全 Kafka
Python IPC机制全攻略:让进程间通信变得像呼吸一样自然
【9月更文挑战第12天】在编程领域,进程间通信(IPC)是连接独立执行单元的关键技术。Python凭借简洁的语法和丰富的库支持,提供了多种IPC方案。本文将对比探讨Python的IPC机制,包括管道与消息队列、套接字与共享内存。管道适用于简单场景,而消息队列更灵活,适合高并发环境。套接字广泛用于网络通信,共享内存则在本地高效传输数据。通过示例代码展示`multiprocessing.Queue`的使用,帮助读者理解IPC的实际应用。希望本文能让你更熟练地选择和运用IPC机制。
48 10
|
9天前
|
数据采集 消息中间件 Python
Python爬虫-进程间通信
Python爬虫-进程间通信
10 0
|
1月前
|
监控 Ubuntu API
Python脚本监控Ubuntu系统进程内存的实现方式
通过这种方法,我们可以很容易地监控Ubuntu系统中进程的内存使用情况,对于性能分析和资源管理具有很大的帮助。这只是 `psutil`库功能的冰山一角,`psutil`还能够提供更多关于系统和进程的详细信息,强烈推荐进一步探索这个强大的库。
35 1
|
1月前
|
Python
惊!Python进程间通信IPC,让你的程序秒变社交达人,信息畅通无阻
【9月更文挑战第13天】在编程的世界中,进程间通信(IPC)如同一场精彩的社交舞会,每个进程通过优雅的IPC机制交换信息,协同工作。本文将带你探索Python中的IPC奥秘,了解它是如何让程序实现无缝信息交流的。IPC如同隐形桥梁,连接各进程,使其跨越边界自由沟通。Python提供了多种IPC机制,如管道、队列、共享内存及套接字,适用于不同场景。通过一个简单的队列示例,我们将展示如何使用`multiprocessing.Queue`实现进程间通信,使程序如同社交达人般高效互动。掌握IPC,让你的程序在编程舞台上大放异彩。
19 3
|
1月前
|
安全 开发者 Python
Python IPC大揭秘:解锁进程间通信新姿势,让你的应用无界连接
【9月更文挑战第11天】在编程世界中,进程间通信(IPC)如同一座无形的桥梁,连接不同进程的信息孤岛,使应用无界而广阔。Python凭借其丰富的IPC机制,让开发者轻松实现进程间的无缝交流。本文将揭开Python IPC的神秘面纱,介绍几种关键的IPC技术:管道提供简单的单向数据传输,适合父子进程间通信;队列则是线程和进程安全的数据共享结构,支持多进程访问;共享内存允许快速读写大量数据,需配合锁机制确保一致性;套接字则能实现跨网络的通信,构建分布式系统。掌握这些技术,你的应用将不再受限于单个进程,实现更强大的功能。
54 5
|
1月前
|
消息中间件 Kafka 数据安全/隐私保护
Python IPC实战指南:构建高效稳定的进程间通信桥梁
【9月更文挑战第11天】在软件开发中,随着应用复杂度的提升,进程间通信(IPC)成为构建高效系统的关键。本文通过一个分布式日志处理系统的案例,介绍如何使用Python和套接字实现可靠的IPC。案例涉及定义通信协议、实现日志发送与接收,并提供示例代码。通过本教程,你将学会构建高效的IPC桥梁,并了解如何根据需求选择合适的IPC机制,确保系统的稳定性和安全性。
45 5
|
1月前
|
存储 安全 数据库
双重防护,无懈可击!Python AES+RSA加密方案,构建最强数据安全堡垒
【9月更文挑战第11天】在数字时代,数据安全至关重要。AES与RSA加密技术相结合,构成了一道坚固防线。AES以其高效性保障数据加密,而RSA则确保密钥安全传输,二者相辅相成,提供双重保护。本文通过Python代码示例展示了这一加密方案的魅力,强调了其在实际应用中的重要性和安全性。使用HTTPS等安全协议传输加密密钥和密文,确保数据在数字世界中自由流通而无忧。
51 1