上一节,亿元程序员为我们简单介绍了Lua运行环境的搭建,我们成功搭建了我们命令行远程打包系统的环境之后,下面我们就可以正式进入我们打包系统的搭建。下面我们跟随亿元程序员一起来看看。
远程打包系统的前后端通信
一.打包系统的后端搭建。
1.首先引入我们前后端通讯需要的socket库。
local socket = require("socket.core")
2.然后绑定端口并且监听连接
local function init()
server_info.port = arg[2] or server_info.port
server = socket.tcp() //创建socket
local r,err=server:bind("*",server_info.port) //绑定监听端口
if err then
log(string.format("端口%d绑定失败,请检查端口.",server_info.port))
os.exit(1)
end
server:setoption("keepalive",true) //保持连接长期活跃
server:listen(5) //监听
server:settimeout(1,'b')
log(string.format("远程打包服务器启动成功,绑定端口:%d.",server_info.port))
end
3.循环监听客户端连接和处理客户端请求
local function main_loop()
while true do
process_accept() //接受客户端连接
local cur_time = os.time()
while os.time()==cur_time do
local read_array,write_array,errmsg =socket.select(select_array,select_array,1)
if errmsg ~= nil and errmsg ~= "timeout" then
log("error: "..errmsg)
elseif errmsg ~= "timeout" then
if #read_array ~= 0 then
process_request(read_array) //处理客户端请求
end
end
end
end
end
4.接受客户端连接
local function process_accept()
local client,msg = server:accept() //接受客户端连接
if client == nil then
if msg ~= "timeout" then
log(msg)
end
else
local ip,port=client:getpeername()
local username =client:receive("*l")
local password =client:receive("*l")
if username == nil or password == nil then
log("username == nil or password == nil")
client:send("<fail>\n")
client:close()
return
end
if (ip == nil or port == nil ) then
log("ip == nil or port == nil")
client:send("<fail>\n")
client:close()
return
end
for _,_client in pairs(clients) do
if (_client ~= nil and _client.user == username) then
client:send("<user_exist>\n")
client:close()
return
end
end
local newc={conn=client,ip=ip, port=port,id=ip..port,user=username,cmd=""}
log(string.format("用户:%s,IP:%s 连接成功.",username or "",ip or ""))
clients[ip..port]=newc
select_array[#select_array+1]= client
newc.slot = #select_array
client:send("<ok>\n")
print_prompt(newc)
end
end
5.处理客户端请求
local function process_request(read_array)
for k=1,#read_array,1 do
local socket = read_array[k]
if(socket ~= nil) then
local ip,port = socket:getpeername()
if(port ~= nil and ip ~= nil ) then
log(ip..":"..port)
local client = clients[ip..port]
if(client ~= nil) then
local line,errmsg = client.conn:receive("*l") //接受客户端信息
if errmsg and errmsg ~= "timeout" or line =="<close>" then
close_client(ip..port)
elseif line then
do_request(client,line) //处理客户端请求
end
end
end
end
end
end
6.响应客户端请求
local function do_request(client,line)
build_service.client=client
log(string.format("用户 %s 发送内容 %s.",client.user, line))
output(string.reverse(line)) //将客户端的内容反转并发回客户端
output("<send_over>")
end
function output(msg)
log(msg)
if build_service.client then
send_msg(build_service.client,msg)
end
end
local function send_msg(client, msg)
if not client.conn then
return
end
local c,err=client.conn:send(msg.."\n") //发送内容给客户端
if err then
log(err)
close_client(client.id)
end
end
7.启动服务端
init()
main_loop()
8.测试!
二.打包系统的前端搭建。
1.连接打包系统服务端
function init(host, port)
local username = arg[1]
local password = arg[2]
if username == nil then
output("请输入用户名")
os.exit(1)
end
if password == nil then
output("请输入密码!")
os.exit(1)
end
host = arg[3] or "127.0.0.1"
port = arg[4] or 6060
g_client = socket.tcp() //创建sockt
g_client:setoption("keepalive",true) //保持活跃
if g_client:connect(host, port) then
g_client:send(username..g_lf)
g_client:send(password..g_lf)
local msg, err = g_client:receive("*l") //接受服务器返回信息
if err or msg~="<ok>" then
if msg == "<fail>" then
output(string.format("用户名与密码不匹配%s", msg))
elseif msg == "<user_exist>" then
output(string.format("不能连接服务器,用户重复登陆"))
else
output(string.format("不能连接服务器,%s.", msg or err ))
end
--sleep(1)
os.exit(1)
else
output(string.format("成功连接服务器,%s,%s.",host,port))
process_response()
end
else
output(string.format("不能连接服务器,%s,%s,请检查服务器是否启动.",host,port))
os.exit(1)
end
end
2.循环接收命令行输入的指令和接收服务端的信息
function main_loop()
while true do
process_request()
end
end
function process_request()
local line = io.read("*l") //接收命令行输入的指令
if g_local_cmd[line] then
g_local_cmd[line]()
print_prompt()
else
send_request(line) //发送指令到服务端
process_response() //接收服务器端信息
end
end
3.发送指令到服务端
function send_request( msg)
local c,err=g_client:send(msg..g_lf) //发送指令到服务端
if err then
close_connect()
os.exit(1)
end
end
4.接收服务端的消息
function process_response()
while true do
echo = g_client:receive("*l") //接受服务端信息
if echo then
if echo=="<send_over>" then
break
else
output(echo)
output("\n")
end
else
break
end
end
print_prompt()
end
5.打印输出本地、服务器信息
function output(msg)
io.stdout:write(msg) //将信息输出到命令行
end
6.启动客户端
init(host,port)
main_loop()
7.测试!
至此,亿元程序员已经为我们成功讲解了如何实现我们远程打包系统的简单的前后端通信。大家可以根据相关关键代码去实现,如果大家有不太理解或者遇到一些问题的,可以关注我们“亿元程序员”,并且尝试在聊天框中输入你遇到的问题,我们定会耐心地为你解答。下一篇文章我们将讲解如何接受客户端的指令并相应处理。