【网络编程】ZeroMQ的网络通信

2024-02-18 11:52

本文主要是介绍【网络编程】ZeroMQ的网络通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1、概述
  • 2、通信效果
    • 2.1、Request-Reply(请求-响应模式)
    • 2.2、Publish-Subscribe(订阅-发布模式)
  • 3、方式选择
    • 3.1、准备用 Visual Studio-C++ 方式
      • 3.1.1、找到 Builds 文件夹
      • 3.1.2、查看 deprecated-msvc 下的 libzmq.sln 文件
      • 3.1.3、使用 Visual Studio 打开 libzmq.sln 解决方案
      • 3.1.4、修改 libzmq.import.props 文件
      • 3.1.5、编译生成
    • 3.2、准备用 PyCharm-Python 方式
      • 3.2.1、安装
        • 3.2.1.1、命令安装
        • 3.2.1.2、IDE安装
      • 3.2.2、查看是否安装成功
  • 4、Request-Reply(请求响应模式)
    • 4.1、Request-Reply模式概述
    • 4.2、Client 源代码
    • 4.3、Server 源代码
  • 5、Publish/Subscribe(订阅-发布模式)
    • 5.1、Pub-Subs模式概述
    • 5.2、发布者 源代码
    • 5.3、订阅者 源代码

1、概述

在前一篇文章中提到了 ØMQ (ZeroMQ) ,是一个基于消息队列的多线程网络库,它封装了网络通信、消息队列、线程调度等功能,向上层提供简洁的API,应用程序通过加载库文件,调用API函数来实现高性能网络通信。

本篇文章重点讲述下,在客户端上如何使用 ZeroMQ 与 服务端的 ZeroMQ 进行通信,主要讲述两种常用模式:
1.Request-Reply(请求响应模式)
2.Publish-Subscribe(订阅-发布模式)

相关文章:

  • 【Qt 学习之路】在 Qt 使用 ZeroMQ:https://shazhenyu.blog.csdn.net/article/details/136051050?spm=1001.2014.3001.5502

2、通信效果

2.1、Request-Reply(请求-响应模式)

Client:
在这里插入图片描述
Server:
在这里插入图片描述

2.2、Publish-Subscribe(订阅-发布模式)

发布者:
在这里插入图片描述
订阅者:
在这里插入图片描述
在这里插入图片描述

3、方式选择

3.1、准备用 Visual Studio-C++ 方式

3.1.1、找到 Builds 文件夹

在 ZeroMQ 的 builds 文件夹下,有很多种编译方法,为了方便演示,本文选择msvc进行演示。
在这里插入图片描述

3.1.2、查看 deprecated-msvc 下的 libzmq.sln 文件

在这里插入图片描述

3.1.3、使用 Visual Studio 打开 libzmq.sln 解决方案

在这里插入图片描述

3.1.4、修改 libzmq.import.props 文件

用 Notepad++ 打开 libzmq.import.props 文件,修改 5处 路径,全部改成…\bin【注意:去掉“…\libzmq\”】

  • 原:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup Label="Globals"><_PropertySheetDisplayName>ZMQ Import Settings</_PropertySheetDisplayName></PropertyGroup><!-- User Interface --><ItemGroup Label="BuildOptionsExtension"><PropertyPageSchema Include="$(MSBuildThisFileDirectory)libzmq.import.xml" /></ItemGroup><!-- Configuration --><ItemDefinitionGroup><ClCompile><PreprocessorDefinitions Condition="'$(Option-sodium)' == 'true'">ZMQ_USE_LIBSODIUM;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-openpgm)' == 'true'">ZMQ_HAVE_OPENPGM;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-gssapi)' == 'true'">HAVE_LIBGSSAPI_KRB5;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-draftapi)' == 'true'">ZMQ_BUILD_DRAFT_API;%(PreprocessorDefinitions)</PreprocessorDefinitions></ClCompile></ItemDefinitionGroup><!-- Linkage --><ItemDefinitionGroup><ClCompile><AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\..\libzmq\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories><PreprocessorDefinitions Condition="'$(Linkage-libzmq)' == 'static' Or '$(Linkage-libzmq)' == 'ltcg'">ZMQ_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions></ClCompile><Link><AdditionalDependencies Condition="'$(Linkage-libzmq)' != ''">libzmq.lib;%(AdditionalDependencies)</AdditionalDependencies><AdditionalLibraryDirectories Condition="$(Configuration.IndexOf('Debug')) != -1">$(ProjectDir)..\..\..\..\..\libzmq\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libzmq)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories><AdditionalLibraryDirectories Condition="$(Configuration.IndexOf('Release')) != -1">$(ProjectDir)..\..\..\..\..\libzmq\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libzmq)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories></Link></ItemDefinitionGroup><!-- Copy --><Target Name="Linkage-libzmq-dynamic" AfterTargets="AfterBuild" Condition="'$(Linkage-libzmq)' == 'dynamic'"><Copy Condition="$(Configuration.IndexOf('Debug')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\..\libzmq\bin\$(PlatformName)\Debug\$(PlatformToolset)\dynamic\libzmq.dll"DestinationFiles="$(TargetDir)libzmq.dll"SkipUnchangedFiles="true" /><Copy Condition="$(Configuration.IndexOf('Debug')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\..\libzmq\bin\$(PlatformName)\Debug\$(PlatformToolset)\dynamic\libzmq.pdb"DestinationFiles="$(TargetDir)libzmq.pdb"SkipUnchangedFiles="true" /><Copy Condition="$(Configuration.IndexOf('Release')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\..\libzmq\bin\$(PlatformName)\Release\$(PlatformToolset)\dynamic\libzmq.dll"DestinationFiles="$(TargetDir)libzmq.dll"SkipUnchangedFiles="true" /></Target><!-- Messages --><Target Name="libzmq-info" BeforeTargets="AfterBuild" Condition="'$(Linkage-libzmq)' == 'dynamic'"><Message Text="Copying libzmq.dll -&gt; $(TargetDir)libzmq.dll" Importance="high"/><Message Text="Copying libzmq.pdb -&gt; $(TargetDir)libzmq.pdb" Importance="high" Condition="$(Configuration.IndexOf('Debug')) != -1" /></Target></Project>
  • 改:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup Label="Globals"><_PropertySheetDisplayName>ZMQ Import Settings</_PropertySheetDisplayName></PropertyGroup><!-- User Interface --><ItemGroup Label="BuildOptionsExtension"><PropertyPageSchema Include="$(MSBuildThisFileDirectory)libzmq.import.xml" /></ItemGroup><!-- Configuration --><ItemDefinitionGroup><ClCompile><PreprocessorDefinitions Condition="'$(Option-sodium)' == 'true'">ZMQ_USE_LIBSODIUM;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-openpgm)' == 'true'">ZMQ_HAVE_OPENPGM;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-gssapi)' == 'true'">HAVE_LIBGSSAPI_KRB5;%(PreprocessorDefinitions)</PreprocessorDefinitions><PreprocessorDefinitions Condition="'$(Option-draftapi)' == 'true'">ZMQ_BUILD_DRAFT_API;%(PreprocessorDefinitions)</PreprocessorDefinitions></ClCompile></ItemDefinitionGroup><!-- Linkage --><ItemDefinitionGroup><ClCompile><AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\..\libzmq\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories><PreprocessorDefinitions Condition="'$(Linkage-libzmq)' == 'static' Or '$(Linkage-libzmq)' == 'ltcg'">ZMQ_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions></ClCompile><Link><AdditionalDependencies Condition="'$(Linkage-libzmq)' != ''">libzmq.lib;%(AdditionalDependencies)</AdditionalDependencies><AdditionalLibraryDirectories Condition="$(Configuration.IndexOf('Debug')) != -1">$(ProjectDir)..\..\..\..\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libzmq)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories><AdditionalLibraryDirectories Condition="$(Configuration.IndexOf('Release')) != -1">$(ProjectDir)..\..\..\..\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libzmq)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories></Link></ItemDefinitionGroup><!-- Copy --><Target Name="Linkage-libzmq-dynamic" AfterTargets="AfterBuild" Condition="'$(Linkage-libzmq)' == 'dynamic'"><Copy Condition="$(Configuration.IndexOf('Debug')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\bin\$(PlatformName)\Debug\$(PlatformToolset)\dynamic\libzmq.dll"DestinationFiles="$(TargetDir)libzmq.dll"SkipUnchangedFiles="true" /><Copy Condition="$(Configuration.IndexOf('Debug')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\bin\$(PlatformName)\Debug\$(PlatformToolset)\dynamic\libzmq.pdb"DestinationFiles="$(TargetDir)libzmq.pdb"SkipUnchangedFiles="true" /><Copy Condition="$(Configuration.IndexOf('Release')) != -1"SourceFiles="$(ProjectDir)..\..\..\..\bin\$(PlatformName)\Release\$(PlatformToolset)\dynamic\libzmq.dll"DestinationFiles="$(TargetDir)libzmq.dll"SkipUnchangedFiles="true" /></Target><!-- Messages --><Target Name="libzmq-info" BeforeTargets="AfterBuild" Condition="'$(Linkage-libzmq)' == 'dynamic'"><Message Text="Copying libzmq.dll -&gt; $(TargetDir)libzmq.dll" Importance="high"/><Message Text="Copying libzmq.pdb -&gt; $(TargetDir)libzmq.pdb" Importance="high" Condition="$(Configuration.IndexOf('Debug')) != -1" /></Target></Project>

3.1.5、编译生成

按照官网的方式,这一步应该是成功了,但是目前是失败,还少文件,可能是包有问题
在这里插入图片描述

3.2、准备用 PyCharm-Python 方式

3.2.1、安装

3.2.1.1、命令安装
pip install pyzmq
3.2.1.2、IDE安装

安装图种方法安装 pyzmq25.1.2 版本
在这里插入图片描述

3.2.2、查看是否安装成功

直接打印 zmq 版本号 试试

import zmq
print(zmq.__version__)

在这里插入图片描述
由于 Python 相对快捷,本文后续以 Python 进行讲述

4、Request-Reply(请求响应模式)

4.1、Request-Reply模式概述

消息双向的,有来有往。
Client请求的消息,Server必须答复给Client。
Client在请求后,Server必须回响应,注意:Server不返回响应会报错。
Server和Client都可以是1:N的模型。通常把1认为是Server,N认为是Client。
更底层的端点地址是对上层隐藏的,每个请求都隐含回应地址,而应用则不关心它。
ZMQ 可以很好的支持路由功能(实现路由功能的组件叫做 Device),把 1:N 扩展为 N:M(只需要加入若干路由节点)。

4.2、Client 源代码

# client.pyimport zmqcontext = zmq.Context()#  Socket to talk to server
print("Connecting to 5555 server…")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")
socket.send(b"Hello, I'm Mr.Sha Client.")
#  Get the reply.
message = socket.recv()
print(f"Received reply [ {message} ]")

4.3、Server 源代码

# server.py
import time
import zmqcontext = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")while True:#  Wait for next request from clientmessage = socket.recv()print("Received request: %s" % message)#  Do some 'work'time.sleep(1)#  Send reply back to clientsocket.send(b"Hello, I'm server.")

5、Publish/Subscribe(订阅-发布模式)

5.1、Pub-Subs模式概述

消息单向,有去无回
一个发布端,多个订阅端;发布端只管产生数据,发布端发布一条消息,可被多个订阅端同时收到。
发布者不必关心订阅者的加入和离开,消息会以 1:N 的方式扩散到每个订阅者。
广播所有client,没有队列缓存,断开连接数据将永远丢失。
如果Publish端开始发布信息时,Subscribe端尚未连接进来,则这些信息会被直接丢弃。
PUB和SUB谁bind谁connect并无严格要求(虽本质并无区别),但仍建议PUB使用bind,SUB使用connect
使用SUB设置一个订阅时,必须使用zmq_setsockopt()对消息进行过滤

这里直接引用官方文档的例子,订阅者再稍作改装!

5.2、发布者 源代码

类似于一个天气更新服务器,向订阅者发送天气更新,内容包括邮政编码、温度、湿度等信息

# Publisher.py
import zmq
from random import randrangecontext = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5556")while True:zipcode = randrange(1, 100000)temperature = randrange(-80, 135)relhumidity = randrange(10, 60)socket.send_string("%i %i %i" % (zipcode, temperature, relhumidity))

5.3、订阅者 源代码

它监听发布者更新的数据流,过滤只接收与特定邮政编码相关的天气信息,默认接收接收10条数据

# Subscribe.py
import sys
import zmq#  Socket to talk to server
context = zmq.Context()
socket = context.socket(zmq.SUB)print("Collecting updates from weather server...")
socket.connect("tcp://localhost:5556")# Subscribe to zipcode, default is NYC, 10001
zip_filter = sys.argv[1] if len(sys.argv) > 1 else "10001"# Python 2 - ascii bytes to unicode str
if isinstance(zip_filter, bytes):zip_filter = zip_filter.decode('ascii')
socket.setsockopt_string(zmq.SUBSCRIBE, zip_filter)# Process 5 updates
total_temp = 0
for update_nbr in range(5):string = socket.recv_string()zipcode, temperature, relhumidity = string.split()total_temp += int(temperature)print("zipcode, temperature, relhumidity:" + string)print("Average temperature for zipcode '%s' was %dF"% (zip_filter, total_temp / (update_nbr + 1))
)

这篇关于【网络编程】ZeroMQ的网络通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/721070

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同