此博客案例是为方便自己查看,给的代码不全可能无法一下看懂,如果不了解Sproto协议的,可以先看下这篇文章:https://blog.csdn.net/sindyra/article/details/108423417
这里我们主要挑出客户端与服务端实际通信时RPC案例讲解下,本案例是一个登陆注册的案例。
1.首先是客户端向服务端发送请求:
local login_args = {name="Bob",password="123456"}
local str = request("login",login_args,session_id) --参数分别为 name ,args , session
name 是消息的字符串名(其实就是消息的类型,如登录消息,授权消息等)、args 是一张保存用消息内容的 table ,而 session 是你提供的唯一识别号,用于让对方正确的回应。 当你的协议不规定需要回应时,session 可以不给出。同样,args 也可以为空。
2.服务器接受到协议:
local function read (fd, size)
return socket.read (fd, size) or error ()
end
local function read_msg (fd)
local buf = read (fd, 2)
--使用小端读取方式,高地址存高位
local protocal_len = buf:byte(1) + buf:byte(2) * 256
--头2字节表示协议总长度 = 协议总长度(2字节)+协议号(2字节)+消息长度
--local protocal_length = string.unpack ("<H", buf) --H代表无符号short,h代表有符号short
skynet.error("recevied msg:")
skynet.error("protocal length:"..protocal_len)
buf = read (fd, protocal_len)
local msg_len = protocal_len - 4
--分割协议,去除协议长度(2字节)和协议号(2字节),只留下消息内容,而消息内容的前2字节也去掉,-
--它是字段的数量。字段部分中的每个字段都是一个16位整数(n)。如果n为零,则表示字段数据在数据-
--部分被编码;
--所以2+2+2=6,即真正消息内容的起始位置为7
local msg = buf:sub(7, protocal_len) --sub(起始位置,结束位置)
skynet.error("msg:"..msg)
return host:dispatch (msg)
end
3.服务器回复消息:
socket.start (fd)
local type, name, args, response = read_msg (fd) --type请求类型(request...),name消息的类型名(.auth...)
skynet.error("type:"..type)
skynet.error("name:"..name)
skynet.error("username:"..args.name)
--read_msg (fd) --type请求类型(request...),name消息的类型名(.auth...)
assert (type == "REQUEST")
if name == "login" then
local user_name = args.name
local user_password = args.password
skynet.error("username:",user_name)
skynet.error("password:",user_password)
for key, value in pairs(user_list) do
if value.name == user_name and value.password == user_password then
local msg = response {
user_exists = true,
session = 1,
}
skynet.error("login success!")
send_msg (fd, msg)
return
end
end
--如果没有找到用户名和密码,登陆失败
local msg = response {
user_exists = false,
}
skynet.error("login failed!")
send_msg (fd, msg)
end