因为最近在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,你好,你是
我是萧蔷