skynet:agent

gateserver 用于管理网络连接,也可以读取网络数据,但它并没有提供发送网络数据相关的写功能,而涉及请求处理与响应一般交给 agent 服务(agent 服务可以由一个普通服务来充当)。

一、agent 服务

myagent.lua

local skynet = require "skynet"
local netpack = require "skynet.netpack"
local socket = require "skynet.socket"


local client_fd = ...
client_fd = tonumber(client_fd)

skynet.register_protocol {
        name = "client",
        id = skynet.PTYPE_CLIENT,
        --需要将网路数据转换成lua字符串,不需要打包,所以不用注册pack函数
        unpack = netpack.tostring,
}

local function task(msg)
        print("recv from fd", client_fd, msg)
        --响应消息的时候直接通过fd发送出去
        socket.write(client_fd, netpack.pack(string.upper(msg)))
end

skynet.start(function()
		--注册client消息专门用来接收网络数据
        skynet.dispatch("client", function(_,_, msg)
        task(msg)

        end)
		
		--注册lua消息,来退出服务
        skynet.dispatch("lua", function(_,_, cmd, ...)
                if cmd == "quit" then
                        skynet.error(client_fd, "agent quit")
                        --skynet.exit()
                end
        end)
end)

二、网关服务

修改上一篇文章中的 mygateserver.lua,为每一个客户端连接创建一个 agent 服务,并把fd、从客户端收到数据就转发给agent服务,同时与客户端的其他交流工作都通过agent来解决。

mygateserver.lua

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


local handler = {}

local agents = {}

function handler.connect(fd, ipaddr)
	skynet.error("ipaddr:",ipaddr,"fd:",fd,"connect")
	gateserver.openclient(fd)

	--连接成功就启动一个agent来代理
	local agent = skynet.newservice("myservice/myagent", fd) 
	agents[fd] = agent
end


--断开连接后,agent服务退出
function handler.disconnect(fd)
	skynet.error("fd:", fd, "disconnect")

	--通过发送消息的方式来退出不要使用skynet.kill(agent)
	local agent = agents[fd]
	if(agent) then
		skynet.send(agent, "lua", "quit")
		agents[fd] = nil
	end
end


function handler.message(fd, msg, sz)
	--skynet.error("recv message from fd:", fd)
	--skynet.error(netpack.tostring(msg, sz))
	
	--收到消息就转发给agent
	local agent = agents[fd]
	skynet.redirect(agent, 0, "client", 0, msg, sz) 
end


function handler.error(fd, msg)
	gateserver.closeclient(fd)
end


function handler.warning(fd, size)
	skynet.skynet("warning fd=", fd , "unsent data over 1M")
end


function handler.open(source, conf) 
	skynet.error("open by ", skynet.address(source))
	skynet.error("listen on", conf.port)
	skynet.error("client max", conf.maxclient)
	skynet.error("nodelay", conf.nodelay)
end

local CMD = {}

function CMD.kick(source, fd)
	skynet.error("source:", skynet.address(source), "kick fd:", fd)
	gateserver.closeclient(fd)
end

function handler.command(cmd, source, ...)
	local f = assert(CMD[cmd])
	return f(source, ...)
end


--注册client消息专门用来将接收到的网络数据转发给agent,不需要解包,也不需要打包
skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
}

gateserver.start(handler)

三、测试

先启动 mygateserver,然后启动客户端 socketclient,然后在 socketclient 所在的控制台输入“hello world!!!”:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值