zoukankan      html  css  js  c++  java
  • Lua zmq和socket通信demo

    因为最近在study lua的一些socket用法,网上的demo稍微整理修改下,作为熟悉了解zmq socket的使用。跟python相比较,其实没差。

    不过就是为了记录修改一下可以run的demo,多敲下代码熟悉熟悉流程。

    Zmq REQ-REP

    客户端发送请求reqeust,服务端接收到REQ请求并作reply响应。

    Server 端:

    local zmq = require "lzmq"  -- 获取zmq的安装包
    local zassert = zmq.assert
    local context = zmq.context()   -- 创建一个ZMQ 上下文  
    local publisher, err = context:socket{zmq.REP, bind = "tcp://*:5025"}  -- 调用套接字  服务端将套接字绑定在端口5025  
    zassert(publisher, err)   -- 开始等待响应 发出应答 如此循环
    --  客户端是发送请求 并等待服务端的应答
    local y = 0
    while y>=0 do 
        local x = "This is a zmq test!"
        y = y + 1
        local ret = zassert(publisher:recv())
        print(y.."rep recv"..ret)
        zassert(publisher:send(x))
        print(y..":"..x)
    end
    
    
    

    Client端:

    local zmq = require "lzmq"
    local zassert = zmq.assert
    local context = zmq.context();
    local requester,err = context:socket{zmq.REQ,connect = "tcp://localhost:5025"}
    zassert(requester,err)
    for i = 1,10 do
        zassert(requester:send("hello"));
        local ret = requester:recv()
        print("req recv==="..ret)
    end
    

    Zmq PUB-SUB

    发布和订阅模式

    1.一个发布者,可以有多个订阅者的关系,1:n;

    2.当发布者数据变化时发布数据,所有订阅者均能够接收到数据并处理

    3.PUB 再发送的时候可以选择性的发送,sub 同样可以选择性的根据订阅的端口名去过滤(比如,下面选择send的时候name设置为端口101,sub端设置订阅101的端口)。

    Pub端:

    --publisher.lua
    local zmq = require("lzmq")
    local timer = require("lzmq.timer")
    local zassert = zmq.assert
    
    local context = zmq.context()
    local address = "tcp://127.0.0.1:10000"
    local zmq_pub,err = context:socket(zmq.PUB,{bind = address})
    zassert(zmq_pub,err)
    print("Create publisher server: ",address)
     
    -- get the time stamp string wih format: %Y-%m-%d %H:%M:%S.ms
    function timeStamp()
        local ms = timer.absolute_time() -- get ms use lzmp.timmer.absolute_time()
        local s = math.floor(ms/1000) -- second
        local date = os.date("%Y-%m-%d %H:%M:%S.", s) -- second to data
        local sub_ms = ms-s*1000 -- just ms
        return date..tostring(sub_ms)
    end
     
    -- publish message
    while true do
        io.write("Publisher> ") -- prompt keyword: "Publisher> "
        io.flush()
        local cmd = io.read("*line") -- read message from cmd line
        if (cmd and #cmd>0) then
            local ret,err=zmq_pub:send("101",zmq.SNDMORE) -- zmq.SNDMORE: 表示发送的消息由多个消息帧组成
            local ret,err=zmq_pub:send(cmd.."
    ")
            if (ret) then
                print(timeStamp(),"[SEND]:",cmd)
            else
                print("[ERROR]:",err)
            end
        end
    end
    
    
    

    SUB端:

    -- subscriber.lua
    local zmq = require("lzmq")
    local timer = require("lzmq.timer")
    local zassert = zmq.assert
    local zpoller = require("lzmq.poller")
    local context = zmq.context();
    local address = "tcp://127.0.0.1:10000"
    local zmq_sub, err = context:socket{zmq.SUB, subscribe = "101"; connect = address; }
    zassert(zmq_sub,err);
    print("[Subscriber]: ","Create subscriber with address : ",address);
    function timeStamp()
        local ms = timer.absolute_time()
        local s = math.floor(ms/1000)
        local date = os.date("%Y-%m-%d %H:%M:%S.", s)
        local sub_ms = ms-s*1000
        return date..tostring(sub_ms)
    end
     
    --poller()解决一个线程中有多个sokect同时需要收发数据时,不用在send()或者recv()时阻塞socket
    --在recv()端接受信息的用zmq.POLLIN
    --在send()端发送消息的用zmq.POLLOUT
    local poller = zpoller.new(2)
    --此处暂时只能用闭包函数,尝试单独写函数来实现时出错
    poller:add(zmq_sub, zmq.POLLIN, function()
        io.write("Receiver> ")
        io.flush()
        print(timeStamp().."	[REV:]	"..zmq_sub:recv())
    end)
    poller:start()
    
    
    
    SUB:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/client.lua
    [Subscriber]: 	Create subscriber with address : 	tcp://127.0.0.1:10000
    Receiver> 2020-07-30 11:21:09.450	[REV:]	101
    Receiver> 2020-07-30 11:21:09.450	[REV:]	1111
    
    PUB:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/server.lua
    Create publisher server: 	tcp://127.0.0.1:10000
    Publisher> 1111
    2020-07-30 11:21:09.449	[SEND]:	1111
    

    Socket通信

    lua 中的socket通信,socket 通过绑定一个IP地址,端口号,来实现两台电脑之间的通信过程。

    Server端:

        -- server.lua
    local socket = require("socket")
    
    -- local host = "127.0.0.1"
    local host = "127.0.0.1"
    local port = "12346"
    local server = assert(socket.bind(host, port, 1024))
    server:settimeout(0)
    local client_tab = {}
    local conn_count = 0
    
    
    print("Server Start " .. host .. ":" .. port) 
    
    while 1 do
        local conn = server:accept()
        if conn then
            conn_count = conn_count + 1
            client_tab[conn_count] = conn
            print("A client successfully connect!") 
        end
        for conn_count, client in pairs(client_tab) do
            local recvt, sendt, status = socket.select({client}, nil, 1)
            if #recvt > 0 then
                local receive, receive_status = client:receive()
                if receive_status ~= "closed" then
                    if receive then
                        assert(client:send("Client " .. conn_count .. " Send : "))
                        assert(client:send(receive .. "
    "))
                        print("Receive Client " .. conn_count .. " : ", receive)   
                        local input, recvt, sendt, status
                    end
                else
                    table.remove(client_tab, conn_count) 
                    client:close() 
                    print("Client " .. conn_count .. " disconnect!") 
                end
            end
    
        end
    end
    

    Client端:

    local socket = require("socket")
    
    local host = "127.0.0.1"
    local port = "12346"
    local sock = assert(socket.connect(host, port))
    sock:settimeout(0)
    
    print("Press enter after input something:")
    
    local input, recvt, sendt, status
    while true do
        input = io.read()
        if #input > 0 then
            assert(sock:send(input .. "
    "))
        end
    
        recvt, sendt, status = socket.select({sock}, nil, 1)
        while #recvt > 0 do
            local response, receive_status = sock:receive()
            if receive_status ~= "closed" then
                if response then
                    print(response)
                    recvt, sendt, status = socket.select({sock}, nil, 1)
                end
            else
                break
            end
        end
    end
    
    Server:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/lua-sockt/server.lua
    Server Start 127.0.0.1:12346
    A client successfully connect!
    Receive Client 1 : 	nihao
    
    Client:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/lua-sockt/client.lua
    Press enter after input something:
    nihao
    Client 1 Send : nihao
    

    改进下,实现一问一答的机制

    Server端:

    local socket = require("socket");
    local host = host or "127.0.0.1";
    local port = port or "12346";
    local server = assert(socket.bind(host, port));
    while true do
        print("server: waiting for client connection...");
        control = assert(server:accept());
        while true do 
            command,status = control:receive();
            if status == "closed" then 
                break 
            else
                print("[client:]",command);
                input = io.read()
                if #input > 0 then
                    assert(control:send(input .. "
    "))
                end
            end
        end
    end
    

    Client端:

    local socket = require("socket")
    
    host = "127.0.0.1"
    port = 12346
    c = assert (socket.connect (host, port))
    print("Press enter after input something:")
    while true do
        input = io.read()
        if #input > 0 then
            assert(c :send(input .. "
    "))
        end
        local s, status, partial = c:receive ()
        if status == "closed" then 
            break 
        else
            print("[Sever:]",s)
        end
    end
    
    Server:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/lua-sockt/server.lua
    server: waiting for client connection...
    [client:]	你好啊
    hi,你好,你是
    [client:]	我是萧蔷
    
    Client:
    xiaoqiangs-MacBook-Pro:~ xiaoqiang$ lua /Users/xiaoqiang/Desktop/lua-sockt/client.lua
    Press enter after input something:
    你好啊
    [Sever:]	hi,你好,你是
    我是萧蔷
    
  • 相关阅读:
    简单工厂模式
    原型模式
    特性Attribute
    MVC_Route层层深入
    异步Async
    sql-connectionStrings
    观察者模式(利用委托)
    SqlServer_存储过程
    c语言----程序记录
    c语言基础笔记
  • 原文地址:https://www.cnblogs.com/xiaoqiangink/p/13403867.html
Copyright © 2011-2022 走看看