skynet_tips

(1)

巼吥1/3  19:59:20
pbc 编码完有没接口获取msg的长度

 云风  20:14:36
pbc_slice 里的长度就是

巼吥1/3  20:41:39
恩   看到了 不过在skynet里面lua里面local buffer = protobuf.encode("tutorial.Person", person)
-- print(buffer)
skynet.ret(buffer,36)


(2)

394463337  20:46:37
有个小问题,新版本的代码里向client发送消息时,为什么强制是TEXT类型的协议啊

云风  20:47:06
发出 skynet 的消息其实是没有协议的
 云风  20:47:25
type 那个信息会丢掉

394463337  20:47:26
但是不是有pack和unpack么
394463337  20:47:35
那这样pack不就没用了
 云风  20:48:00
client 本身一般都根据项目需要自己写的
 云风  20:48:25

我们的项目就封装了一个 protobuffer 协议的 client


(3)

巼吥1/3  20:48:57
pbc  和skynet要怎么结合  还没搞懂    send的时候要msg 和size   可是pbc里面出来的好像不行
 云风  20:49:14
skynet client 本身是一个内部 serivce, 它可以拿到 type, session id, data 等等
 云风  20:49:20
然后打包发出去
394463337  20:50:05

对,就是向这个内部client-service发送的时候也是无类型的么



 云风  20:51:19
static struct pack_proto *PB = NULL;

#define MAX_HEADER 64
#define MAX_SEND_BUF 65535

struct client {
    int id;
};

/*
老的游戏协议包, 包协议用 protobuffer
package proto;

message Pack
{
optional    int32   session  = 1;
optional    int32   type     = 2;
optional    bytes   data     = 3;
}

当 type > 0 时, 表示是一个请求包. session 为一个 >0 的正数.
当 type == 0 时, 表示是一个回应包. session 为一个 >0 的正数, 对应之前发过来的请求包中的 session.

转换到新内部协议:
msg 的前两个字节必须是 type 字段. 之后是 protobuffer 包
 */
static int
_cb(struct skynet_context * context, void * ud, int stype, int session, uint32_t source, const void * msg, size_t sz) {
assert(sz <= 65535);
struct client * c = (struct client*) ud;

        size_t  buflen  = sz + MAX_HEADER;
        uint8_t *buffer = malloc(buflen);
struct ejoy_pack package;
uint16_t type = 0;

package.session = session;

if (stype == PTYPE_RESPONSE) {
package.type = 0;
package.data.buffer = (void *)msg;
package.data.len = sz;
} else {
assert(stype == PTYPE_EJOY_PACKAGE);
const uint8_t *header = msg;
type = header[0] << 8 | header[1];
package.type = type;

package.data.buffer = (void *)((uintptr_t)msg + sizeof(type));
package.data.len = sz - sizeof(type);
}

struct pbc_slice slice;
slice.buffer = buffer + 2;
slice.len = buflen - 2; 

int err = pbc_pattern_pack(PB->pack, &package , &slice);
assert(err>=0);
assert(slice.len <= 65535);

buffer[0] = (slice.len >> 8) & 0xff;
buffer[1] = slice.len & 0xff;

        skynet_socket_send(context, c->id, buffer, slice.len + 2);

return 0;
}
 云风  20:51:27
这是我们一个项目的 client
394463337  20:52:44
哦,知道了,谢谢啊,client-service都是自己来定制的喽
 云风  20:53:19
我们把一个 skynet 内部的消息,附加上 session 然后按 pb 打包
 云风  20:53:54
这里我们就限制发送给 client 的 type 一定是 PTYPE_EJOY_PACKAGE
 云风  20:54:10

如果不是,一定是写错了,也无法打包

394463337  20:54:18
嗯,明白了
394463337  20:54:18
if (type == PTYPE_RESERVED_ERROR) {
// todo: tell client the session is broken
return 0;
}
if (type == PTYPE_RESPONSE) {
// todo: response to client with session, session may be packed into package
} else {
printf("client %d\n",type);
assert(type == PTYPE_TEXT);
// todo: support other protocol
}
// todo: design
394463337  20:54:35
这个最新版的代码,我是用的时候感到奇怪
巼吥1/3  20:54:41
哦     那在skynet的lua层要怎么调用
394463337  20:54:58
明白了现在
394463337  20:55:23
skynet用lua时是要先注册协议的
394463337  20:55:33
一个lua service先注册协议
394463337  20:56:05
像TEXT是属于通用的一种,打解包方式是定义在你注册的protocol里的pack-unpack里的


(4)

云风  20:56:2

function ejoy.dispatch(session, address, type,msg,sz)

local info = skynet.trace()
local trace_tmp = {}
trace_cache[info] = trace_tmp
assert(type>0)
local message = pbu.lookup(type)
local data = pb.decode(message.input , msg, sz)
trace_tmp.message = message
trace_tmp.data = data
local routine = assert(message_table[message.name], message.name)
routine(data, address , session)
end


function ejoy.dispatch_client(session, address , msg, sz, type)
return ejoy.dispatch(session, address, type, msg, sz)
end


skynet.register_protocol {
name = "ejoy",
id = 14,
pack = function (...) return ... end,
unpack = function(...)
return ejoypack.extract_type(...)
end,
dispatch = ejoy.dispatch,
}

skynet.register_protocol {
name = "ejoy_client",
id = 15,
unpack = function (...) return ... end,
dispatch = ejoy.dispatch_client,
}
394463337  20:56:27
调用的时候还是skynet.send或skynet.call,参数会经过你注册的pack出去
 云风  20:56:41
我们 server 收到 client 发来的消息这样处理的
 云风  20:58:47
主要是这一行
unpack = function(...)
return ejoypack.extract_type(...)
end,
 云风  21:00:00
对应前面的
const uint8_t *header = msg;
type = header[0] << 8 | header[1];
package.type = type;
 云风  21:00:46
我们 C/ S 通讯额外有一个整数表示协议号的,就是这个 type, 和 skynet 的 type 是两个东西


(5)

394463337  21:00:53
云大,skynet里检测到断线是怎么处理的啊,我目前是watchdog检测到通知agent来做清理的,但是我看你的BLOG也提到,需要一种优雅的方式来处理么
 云风  21:01:33
断线是在 gate 里检测到,发给 watchdog 后,最终转化为游戏内部协议的
 云风  21:01:54
就是 socket 断了后,最终处理的代码会收到一条明确的协议
394463337  21:02:07
嗯,这个我理解的
 云风  21:02:55
断线我们现在等同于玩家主动退出,行为是一致的


(6)

 云风  21:03:46
接上面那个, 我们设计的比较早,方法未必好. 当时区分了 ejoy 和  ejoy_client
 云风  21:03:59
ejoy 指一种在 skynet 内部流通的协议
 云风  21:04:18
ejoy_client 指同样的协议,但需要经过打包变成一个数据块
 云风  21:04:57
因为 skynet 内部的协议 是 session type data 的复合体,但和 client 交流只能有一个数据块





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值