nanomsg使用

nanomsg是一个消息通信组件 - zeromq的作者之一用C语言重写的通信框架,
使用宽松的MIT许可开源,小、轻、快,非常方便,介绍我就不多写了,下面我具体的讲用法,用了你就知道是怎么回事。

pull/push 单向管道推送模式

push/pull套接字结合使用可实现消息队列的扇出模式,
这是一个1对多的模式,服务端不能有多个,但客户端可以多个。
官网上给的这个图是1对1的,不要误解(他实际上是用于1对多的):



服务端或客户端不管谁先启动,都会等待对方连接,
注意pub/sub模式的服务端启动后是不会等待客户端来连接的,而push/pull就完全相反必须双方连接好了再推送,可以想象为一个管道,两头都接上才能传输数据。

pub/sub模式中,服务端一旦跟客户端连接,中间就绝不会丢弃消息,
就类似于一个单向的数据流,服务端只发不收,客户端只收不发,一个消息不会重复发给多个客户端
一般用于任务分派、负载均衡。

push服务端示例:
import console; 

import nnmsg;
var sock = nnmsg.socket.push();
sock.bind (
"ws://*:7715"

console.log(
"push服务端等待连接中,没有人连接是不会发送的")

for(i=1;100;1){
      
    sock.send(
"分发任务ID:" + i );
    console.log(
"分发任务ID:" + i )
    
sleep(1000)


console.pause(
true);

pull客户端示例:

import console; 

import nnmsg;
var sock = nnmsg.socket.pull();

console.log("客户端等待连接")
if( sock.connect("ws://127.0.0.1:7715") ){
    
    
var s = sock.recv();
    
while(s){
        console.log(
"服务器返回:",s );
        s = sock.recv();
    }
    
}
console.pause(
true);
   

千万不要以为这有什么呀,自己写个套接字也可以推送点东西,

nanomsg可没有这么简单,表面上看起来他好像是一个传输流,实际上他并不是。

 

nanomsg不像传统套接字那样,一定要服务端先启动,客户端后面跑过来连接,

他也可以客户端先启动,服务端后启动。

 

而且在连接传输的过程中,服务端,或者是客户端都可以中途断线,

下次再启动,可以继续工作,很神奇是吧?!

sub/pub 消息广播模式

sub/pub套接字结合使用可实现消息广播模式(Topics && Broadcast)
服务端只管发布,不管客户端是否连接,也不管是不是丢消息,但客户端连接上来以后就不会丢消息。



这个模式与push/pull的区别是很明显的,
不会像push/pull那样一定要等待双方连接才传输数据。
pub服务端只管自己顾自己的发布消息,而不管别人有没有收到。
一个典型的例子就是报时服务器,下面看代码。

pub服务端:

import console; 

import nnmsg;
var sock = nnmsg.socket.pub();
sock.bind (
"ws://*:7713"

console.log(
"pub服务端已启动,不管客户端是不是连接上来,也不考虑有没有人接收消息")

for(i=1;100;1){
      
    sock.send(
"报时:" + tostring( time() ) );
    console.log(
"报时:" + tostring( time() )  )
    
sleep(1000)


console.pause(
true);

sub客户端:

import console; 

import nnmsg;
var sock = nnmsg.socket.sub();

console.log(
"客户端等待连接")

//一定要指定订阅的主题前缀,指定为空订阅所有主题
sock.subscribe("报时:");

if( sock.connect("ws://127.0.0.1:7713") ){
    
    
var s = sock.recv();
    
while(s){
        console.log(
"服务器返回:",s );
        s = sock.recv();
    }
    
}
console.pause(
true);
   

这个sub客户端有一点特别,一定要用 sock.subscribe("报时:"); 指定你感兴趣的消息,

这个函数的参数指定要订阅消息的前几个字符,这几个字符没有特别格式的要求,只要消息是由这几个字符开始就可以。

 

pus/sub模式里,服务端的同一个消息可能被多个客户端接收,也可能根本没有客户端接收,

push/pull则完全不同 - 服务端消息一定会被一个客户端,并且也只会被一个客户端取走。

surveyor/respondent调查者模式

surveyor/respondent套接字结合使用可实现调查模式,
surveyort负责发出调查问题,而respondent客户端则负责回应。



surveyor 服务端示例:

import console; 

import nnmsg;
var sock = nnmsg.socket.surveyor();
sock.bind (
"ws://*:7717"

console.log(
"已启动 Survey(WebSocket协议) 服务端")
while (1){   
    
var msg  = sock.send("客户端你好,现在几点了?");
    
while(1){
        
var tm,err = sock.recvTable();
        
if(!tm){
            
if(nnmsg.lasterrno() == 0x9523DFE/*_NN_EFSM*/ ) break ;
            
else continue ;  
        }
        console.log( tm )
    }
     
    console.log(
"调查完了")   
}
  

respondent客户端:

import console; 
import nnmsg;

console.log(
"Survey(WebSocket协议)客户端已启动")
var sock = nnmsg.socket.respondent();

if( sock.connect("ws://127.0.0.1:7717") ){
    
while(1){
       
var msg  = sock.recv();
        console.dump( 
"收到:",msg );
        sock.sendTable( time() )
    } 
}

console.pause(
true);

 

pair 端对端双向通信模式

pair套接字,服务端和客户端可以1对1的收发消息,


pair 服务端:
import console; 

import nnmsg;
var sock = nnmsg.socket.pair();
sock.bind (
"ws://*:7710"

console.log(
"已启动 WebSocket 服务端")
while (1){   
    
var msg  = sock.recv();
    console.dump( 
"客户端:",msg );    
    sock.send(
"客户端你还好吗?!"
}

console.pause(
true);

pair 客户端:

import console; 

import nnmsg;
var sock = nnmsg.socket.pair();
if( sock.connect("ws://127.0.0.1:7710") ){
    sock.send(
"hello"
    console.log(
"服务端:",sock.recv() )
}
console.pause(
true);
   

bus 消息总线模式

一个消息总线上可以有多个套接字,
每个套接字即是服务端可以启动监听,也是客户端可以同时连接多个其他的套接字。

连接到消息总线的任何一个套接字发送消息,消息总线上的其他套接字都能收到,一个套接字发出的消息,
其他套接字有可能重复的接收到多次(这个就好比街头听到的小道消息,可能由不同的人告诉你)。
但是套接字永远不会收到自己发的消息。




下面请看演示,消息总线里不分服务端或者客户端:
import win.ui;
/*DSG{{*/
var winform = win.form(text="nanomsg消息总线模式 演示";right=759;bottom=469)
winform.add(
edit={cls=
"edit";left=17;top=18;right=739;bottom=445;db=1;dl=1;dr=1;dt=1;edge=1;multiline=1;vscroll=1;z=1}
)

/*}}*/

winform.show() 

//用于启动一个节点线程
var joinbus = function(port,winform){
    
import win;
    
import nnmsg;
    
    
var sock = nnmsg.socket.bus();
    sock.bind (
"tcp://*:" + port) 
    
    
var nodes = thread.get("nnmsg-bus") : {}; 
    
for(i,addr in nodes){ 
        sock.connect(addr)
//连接到消息总线上所有其他的节点
    }
    
//把自己的地址写到消息总线上去
    table.push(nodes,"tcp://127.0.0.1:" + port);
    thread.set(
"nnmsg-bus",nodes ) 
      
    
sleep(100);//等待其他节点加入
    sock.send(port + "发送:我是新人,我今天才刚知道这个消息总线" ) 
    
    
while( win.isWindow(winform.hwnd) ){   
        
var msg  = sock.recv();
        winform.edit.print(port + 
"接收:" + msg)
    }
}


//创建一大堆节点模拟消息总线
for(port=7591;7599){
    thread.invoke(joinbus,port,winform)  
sleep(100);
}

win.loopMessage();

运行示例可以看到,这个模式发送的消息发送的还是有些激烈的,所以这种模式只适合在本地局域网内使用。

使用WebSocket客户端与nanomsg交互

nanomsg实现各种模式的代码惊人的简洁,但简洁不等于简单。
并且各种编程语言里基本都有nanomsg的实现,使用nanomsg有良好的可扩展性。

nanomsg不但可以实现多种不同的通信模式,也可以选择多种不同的通信协议。
例如上面的我写的消息总线模式 - 使用的是tcp协议,而其他的模式使用的是WebSocket协议。
尤其是其中的WebSocket协议非常有趣,我们可以自己写一个WebSocket去连接nanomsg的服务端,并与nanomsg交互。

最初尝试的时候,我失败了!
在aardio中使用 web.socket.client 对象去连接 nanomsg,nanomsg很不高兴的拒绝了连接。

于是,我想起了 wsock.tcp.simpleHttpServer 这个好东西,
首先我用 wsock.tcp.simpleHttpServer启动了一个HTTP服务端 - 用来冒充nanomsg服务端。
然后用 nanamsg创建了一个WebSocket客户端连接上去,在HTTP服务器上输出发过来的数据包,
发现了nanomsg的小秘密,多了一个Sec-WebSocket-Protocol的HTTP头。

好吧,下面我们看演示代码。

nanomsg 服务端:
import console; 

import nnmsg;
var sock = nnmsg.socket.pub();
sock.bind (
"ws://*:7725"

console.log(
"pub服务端已启动,可以打开aardio websocket客户端试一下了")

for(i=1;100;1){
      
    sock.send(
"报时:" + tostring( time() ) );
    console.log(
"报时:" + tostring( time() )  )
    
sleep(1000)


console.pause(
true);
 

下面是aardio实现的WebSocket客户端:

import win.ui;
/*DSG{{*/
var winform = win.form(text="WebSocket客户端演示";right=770;bottom=467)
winform.add(
btnClose={cls=
"button";text="断开";left=681;top=295;right=757;bottom=333;db=1;dr=1;z=6};
btnOpen={cls=
"button";text="连接WebSocket服务端";left=501;top=295;right=655;bottom=333;db=1;dr=1;z=2};
btnSend={cls=
"button";text="发送数据";left=567;top=380;right=764;bottom=456;db=1;dr=1;z=4};
cbSecWebSocketProtocol={cls=
"combobox";left=301;top=298;right=481;bottom=324;edge=1;items={};mode="dropdown";z=7};
txtMessage={cls=
"edit";left=29;top=22;right=741;bottom=285;db=1;dl=1;dr=1;dt=1;edge=1;multiline=1;z=1};
txtSend={cls=
"edit";text="WebSocket测试";left=25;top=382;right=554;bottom=457;db=1;dl=1;dr=1;edge=1;multiline=1;z=3};
txtUrl={cls=
"edit";text="ws://127.0.0.1:7725";left=29;top=295;right=269;bottom=331;db=1;dl=1;dr=1;edge=1;z=5}
)

/*}}*/

winform.cbSecWebSocketProtocol.items ={
    
"pub.sp.nanomsg.org";
    
"sub.sp.nanomsg.org";
    
"pair.sp.nanomsg.org";
    
"req.sp.nanomsg.org";
    
"rep.sp.nanomsg.org";
    
"surveyor.sp.nanomsg.org";
    
"respondent.sp.nanomsg.org";
    
"push.sp.nanomsg.org";
    
"pull.sp.nanomsg.org";
    
"bus.sp.nanomsg.org";
}


import web.socket.client;
var ws = web.socket.client();
ws.heartbeatInterval = - 1;
//sub端不能发任何数据

ws.onOpen = function(){
    winform.cbSecWebSocketProtocol.disabled = 
true;
}

ws.onClose = 
function(){
    winform.txtMessage.print(
"onClose");
    winform.cbSecWebSocketProtocol.disabled = 
false;
    winform.btnSend.disabledText = 
null;
}

ws.onError = 
function(err){
    winform.txtMessage.print(
"onError",err);
}

ws.onMessage = 
function(msg){
    winform.txtMessage.print(msg.data); 
}

winform.btnSend.oncommand = 
function(id,event){
    ws.send(winform.txtSend.text)   
}

winform.btnOpen.oncommand = 
function(id,event){
    
//加上这句,假装自己是nanomsg客户端
    ws.headers ={
        [
"Sec-WebSocket-Protocol"] = winform.cbSecWebSocketProtocol.selText;
    }
    
    
if( winform.cbSecWebSocketProtocol.selText == "pub.sp.nanomsg.org" ){
        winform.btnSend.disabledText = 
"此模式不支持发送"
    }
    ws.connect(winform.txtUrl.text);
}

winform.btnClose.oncommand = 
function(id,event){
    ws.close();
}

winform.show() 
win.loopMessage();


运行示例,奇迹发生了:

<think>首先,用户的问题是:“我想获取nanomsg库的使用方法 请问nanomsg使用指南”。他们指定了参考站内引用,所以我需要根据提供的引用来回答。 提供的引用有: - [^1]: Node-nanomsg安装与使用指南。包含项目目录结构等。 - [^2]: nanomsg使用高效的内存池机制。 - [^3]: nanomsg-python 使用指南,示例代码。 - [^4]: nanomsg在Docker与Podman中的配置指南。 - [^5]: nanomsg异步接口的使用。 用户上一次的问题是:“我想获取nanomsg库的使用方法 请问nanomsg使用指南”,这是当前查询。 系统级指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 由于用户的问题是关于nanomsg库的使用指南,我需要基于引用提供的信息。引用覆盖了不同方面:Node.js版本、Python版本、内存管理、容器配置、异步接口。 我的回答应该结构化: 1. **介绍**:简要介绍nanomsg库。 2. **安装指南**:引用[^1]和[^3]提到安装。 3. **基本使用方法**:引用[^3]有Python示例,引用[^1]有Node.js相关内容。 4. **高级特性**:包括内存管理(引用[^2])、异步接口(引用[^5])、容器配置(引用[^4])。 5. **总结**。 6. **生成相关问题**:在末尾添加相关问题。 在回答中,当引用特定信息时,在末尾添加引用标识如[^1]。 确保没有数学表达式,所以不需要使用LaTeX数学格式。 回答使用中文。 生成相关问题: - 基于用户查询,例如: - 如何在不同语言中使用nanomsg? - nanomsg的性能优化技巧? - nanomsg在容器环境中的部署? 结构化回答: 1. **步骤1:介绍nanomsg库** - 解释nanomsg是什么:一个轻量级消息通信库。 - 基于引用,提到它用于高性能网络通信。 2. **步骤2:安装指南** - 引用[^1]:Node.js版本安装。 - 引用[^3]:Python版本安装。 - 简要说明如何安装。 3. **步骤3:基本使用方法** - 引用[^3]:Python示例代码。 - 引用[^1]:Node.js指南。 4. **步骤4:高级功能** - 内存管理(引用[^2])。 - 异步接口(引用[^5])。 - 容器配置(引用[^4])。 5. **步骤5:总结** - 鼓励用户尝试。 6. **相关问题** - 列出3-5个相关问题。 在代码块中显示示例代码,如引用[^3]中的Python代码。 确保引用标识自然地添加在相关段落末尾。 完整回答: - 开头:直接回应用户的查询。 - 正文:逐步解释。 - 结尾:相关问题。 </think>### nanomsg使用指南 nanomsg是一个轻量级、高性能的分布式消息通信库,支持多种编程语言(如Python、Node.js)和通信模式(如PAIR、PUB/SUB)。它通过高效的内存管理和异步I/O机制,确保低延迟和高吞吐量[^1][^5]。以下是基于参考引用的完整使用指南,我将逐步介绍安装、基本使用、核心功能和高级配置。 #### 步骤1: 安装nanomsg库 首先,安装nanomsg库取决于您使用的编程语言。以下是常见语言的安装方法: - **Python**:使用`nanomsg-python`库,通过pip安装。 ```bash pip install nanomsg ``` 安装成功后,即可在代码中导入模块[^3]。 - **Node.js**:使用`node-nanomsg`库,通过npm安装。 ```bash npm install nanomsg ``` 安装后,项目目录通常包含`lib`(核心代码)、`examples`(示例)和`config`(配置文件)等文件夹[^1]。 - **C/C++**:从官方仓库编译安装(详细步骤见nanomsg官网)。 #### 步骤2: 基本使用方法(以Python为例) nanomsg支持多种通信协议,如`PAIR`(点对点)、`PUB/SUB`(发布订阅)。以下是一个简单的Python示例,实现双向通信: ```python from nanomsg import Socket, PAIR # 创建两个配对Socket s1 = Socket(PAIR) s1.bind('tcp://*:5555') # 绑定地址 s2 = Socket(PAIR) s2.connect('tcp://localhost:5555') # 连接地址 # 发送和接收消息 s1.send(b'Hello from s1') msg = s2.recv() # 接收消息,输出: b'Hello from s1' print(msg) s1.close() s2.close() ``` 此代码演示了PAIR模式的绑定(`bind`)和连接(`connect`),确保在同一主机上进行通信。您可替换协议为`PUB`或`SUB`实现广播功能[^3][^5]。 #### 步骤3: 核心功能详解 - **内存管理**:nanomsg使用高效内存池机制(如`nn_chunk_alloc`函数),通过预分配内存块减少系统调用开销,支持共享内存和引用计数[^2]。 - **异步通信**:利用事件驱动和非阻塞I/O(如`nn_poll`接口)。优化建议: - 使用`NN_SNDBUF`和`NN_RCVBUF`调整缓冲区大小。 - 结合线程池处理并行任务,提升吞吐量[^5]。 - **传输模式**:支持`inproc`(进程内)、`ipc`(进程间)和`tcp`(网络)三种模式。示例中`inproc://bob`表示进程内通信[^3][^4]。 #### 步骤4: 高级配置(容器环境) 在Docker或Podman容器中部署时,需配置跨主机通信: 1. **容器内部署**:在Dockerfile中安装nanomsg库,并暴露端口(如`EXPOSE 5555`)。 2. **跨主机通信**:使用TCP模式(如`tcp://host_ip:port`),确保网络权限。 3. **性能优化**: - 启用零拷贝机制减少数据复制。 - 结合事件循环(如libuv)实现高并发[^4][^5]。 #### 总结 通过以上指南,您可快速集成nanomsg到项目中,实现高性能消息通信。重点包括正确安装库、选择合适协议,以及优化内存和异步处理。实践中,建议从简单用例开始,逐步扩展到分布式场景[^1][^3][^5]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值