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.."\r\n")
        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().."\t[REV:]\t"..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 .. "\n"))
                    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 .. "\n"))
    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 .. "\n"))
            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 .. "\n"))
    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,你好,你是
我是萧蔷

猜你喜欢

转载自www.cnblogs.com/xiaoqiangink/p/13403867.html
LUA
今日推荐