Skynet基础入门例子详解(7)

25 篇文章 9 订阅
9 篇文章 14 订阅

GateServer的使用

skynet 提供了一个通用模板 lualib/snax/gateserver.lua 来启动一个网关服务器,通过 TCP 连接和客户端交换数据。

TCP 基于数据流,但一般我们需要以带长度信息的数据包的结构来做数据交换。gateserver 做的就是这个工作,把数据流切割成包的形式转发到可以处理它的地址。
skynet 提供了一个 lua 库 netpack ,用来把 tcp 流中的数据解析成 长度 + 内容的包。
gateserver就是使用netpack进行包解析。

在同一个目录建立7个文件(config,proto.lua,main.lua,mygate.lua,socket1.lua,service1.lua,client1.lua)

本例子的client1使用前两节的client,代码稍作修改。

client1.lua代码:

package.cpath = "luaclib/?.so"
package.path = "lualib/?.lua;myexample/e5/?.lua"

if _VERSION ~= "Lua 5.3" then
	error "Use lua 5.3"
end

local socket = require "clientsocket"

-- 通信协议
local proto = require "proto"
local sproto = require "sproto"

local host = sproto.new(proto.s2c):host "package"
local request = host:attach(sproto.new(proto.c2s))

local fd = assert(socket.connect("127.0.0.1", 8888))

local session = 0

-- 封包(长度+内容)
local function send_package(fd, pack)
	local package = string.pack(">s2", pack)
	socket.send(fd, package)
end

local function send_request(name, args)
	session = session + 1
	local str = request(name, args, session)

	-- socket.send(fd, str)

	-- 添加数据长度包头,gateserver接收自动判断类型为data(gateserver使用了netpack进行解析)
	-- skynet 提供了一个 lua 库 netpack ,用来把 tcp 流中的数据解析成 长度 + 内容的包。
	send_package(fd,str);

	print("Request:", session)
end

send_request("handshake")
send_request("say", { name = "soul", msg = "hello world" })

while true do
	-- 接收服务器返回消息
	local str   = socket.recv(fd)

	-- print(str)
	if str~=nil and str~="" then
            print("server says: "..str)
            -- socket.close(fd)
			-- break;
    end

	-- 读取用户输入消息
	local readstr = socket.readstdin()

	if readstr then
		if readstr == "quit" then
			send_request("quit")
			-- socket.close(fd)
			-- break;
		else
			-- 把用户输入消息发送给服务器
			send_request("say", { name = "soul", msg = readstr })
		end
	else
		socket.usleep(100)
	end

end

socket1.lua代码:

local skynet = require "skynet"
local common = require "common"

local gate

skynet.start(function()
	print("==========Socket Start=========")
	print("Listen socket :", "127.0.0.1", 8888)

	-- Socket服务配置
	local conf = {
		address = "127.0.0.1",
		port = 8888,
		maxclient = 1024,
		nodelay = true,
	}

	-- common:dump(conf)
	-- 启动Socket管理网关
	gate=skynet.newservice("mygate")

	-- 打开监听端口
	skynet.call(gate, "lua", "open" , conf)

end)

mygate.lua代码:

local skynet = require "skynet"
local gateserver = require "snax.gateserver"
local netpack = require "netpack"
local common = require "common"

local connection = {}	-- fd -> connection : { fd , ip }
local handler = {}

local agentlist = {}

-- 当一个完整的包被切分好后,message 方法被调用。这里 msg 是一个 C 指针、sz 是一个数字,表示包的长度(C 指针指向的内存块的长度)。
function handler.message(fd, msg, sz)
	print("===========gate handler.message============"..fd)
	-- common:dump(connection[fd])

	local c = connection[fd]
	local agent = agentlist[fd]
	if agent then
		-- skynet.redirect(agent, c.client, "client", 1, msg, sz)
		print("接收到客户端消息,传给agent服务处理")
	else
		print("没有agent处理该消息")
	end
end

function handler.connect(fd, addr)
	print("===========gate handler.connect============")
	local c = {
		fd = fd,
		ip = addr,
	}
    -- common:dump(c)
	-- 保存客户端信息
	connection[fd] = c

    -- 马上允许fd 接收消息(由于下面交给service1处理消息,所以可以在service1准备好再调用)
    -- 这样可能导致客户端发来的消息丢失,因为service1未准备好的情况下,无法处理消息
    gateserver.openclient(fd)

    agentlist[fd] = skynet.newservice("service1")
	skynet.call(agentlist[fd], "lua", "start", { fd = fd, addr = addr })
end

function handler.disconnect(fd)
	print(fd.."-断开连接")
end

function handler.error(fd, msg)
	print("异常错误")
end

gateserver.start(handler)

service1.lua代码:

local common = require "common"
local skynet = require "skynet"
require "skynet.manager"	-- import skynet.register

local CMD = {}
local client_fd
local host

-- TODO
-- skynet.register_protocol
-- 注册新的消息类别 PTYPE_CLIENT,新的类别必须提供 pack 和 unpack 函数,用于消息的编码和解码。

function CMD.start(conf)
	print("service1 CMD.start")
	-- common:dump(conf)
	-- SOCKET处理
end

function CMD.disconnect()
	-- todo: do something before exit
	skynet.exit()
end

skynet.start(function()
	print("==========Service1 Start=========")
	skynet.dispatch("lua", function(session, address, cmd, ...)
		print("==========Service1 dispatch============"..cmd)
		local f = CMD[cmd]
		skynet.ret(skynet.pack(f(...)))
	end)
end)

项目源码:http://download.csdn.net/detail/uisoul/9806650
API参考文档:https://github.com/cloudwu/skynet/wiki/GateServer

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值