├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── client.sh ├── config ├── luaclib └── protobuf.so ├── lualib ├── comfun.lua ├── log.lua ├── protobuf.lua ├── protopack.lua ├── retcode.lua └── utils.lua ├── makefile ├── proto ├── pbhead.pb ├── pbhead.proto ├── pblogin.pb └── pblogin.proto ├── run.sh └── service ├── main.lua ├── pbc.lua ├── sockhandler.lua └── watchdog.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "skynet"] 2 | path = skynet 3 | url = https://github.com/cloudwu/skynet.git 4 | 5 | [submodule "3rd/pbc"] 6 | path = 3rd/pbc 7 | url = https://github.com/cloudwu/pbc.git 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Four 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | skynet使用pbc解析protobuf,使用socket和客户端通信。 2 | 3 | # 服务器编译步骤: 4 | clone完整的代码 代码中引用了skynet和pbc 5 | git clone [https://github.com/bytemode/skynet_pbc](https://github.com/bytemode/skynet_pbc) 6 | 7 | cd skynet_pbc 8 | git submodule init 9 | git submodule update 10 | 11 | cd skynet 12 | git submodule init 13 | git submodule update 14 | 15 | # 编译skynet 16 | cd skynet 17 | make linux 18 | 19 | # 编译pbc 20 | cd ../3rd/pbc 21 | make 22 | 23 | cd binding 24 | cd lua53 25 | make 26 | 27 | 如果提示找不到lua.h则需要安装一下lua5.3. make && make install 28 | (或者修改一下Makefile文件,设置lua.h的路径) 29 | 30 | 将protobuf.lua复制到根目录的lualib目录 31 | protobuf.so文件复制到根目录的luaclib目录 32 | 33 | # 编译proto文件 34 | 回到根目录 35 | make 36 | 37 | 如果没有安装protobuf的话会报错,因为要使用到protoc 38 | yum install protobuf-devel.x86_64 39 | yum install protobuf.x86_64 40 | 41 | # 运行 42 | . run.sh 43 | 具体教程见wiki 44 | 45 | # 使用cocos2dx 测试一下连接。 46 | clinet的地址: 47 | https://github.com/bytemode/cocos2dx_lua_skynet_client.git 48 | -------------------------------------------------------------------------------- /client.sh: -------------------------------------------------------------------------------- 1 | ./skynet/3rd/lua/lua test/client.lua 2 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | root="./" 2 | thread = 8 3 | logger = nil 4 | logpath = "." 5 | harbor = 1 6 | address = "127.0.0.1:2536" 7 | master = "127.0.0.1:2033" 8 | start = "main" -- main script 9 | bootstrap = "snlua bootstrap" -- The service for bootstrap 10 | standalone = "0.0.0.0:2033" 11 | luaservice = "./service/?.lua;./skynet/service/?.lua;" 12 | lualoader = "./skynet/lualib/loader.lua" 13 | lua_path = "./lualib/?.lua;./skynet/lualib/?.lua;./skynet/lualib/?/init.lua" 14 | lua_cpath = "./luaclib/?.so;./skynet/luaclib/?.so" 15 | cpath = "./skynet/cservice/?.so" 16 | -- daemon = "./skynet.pid" 17 | -------------------------------------------------------------------------------- /luaclib/protobuf.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytemode/skynet_pbc/387da1a1d988d3cca9400d140fa4e120c1fedc04/luaclib/protobuf.so -------------------------------------------------------------------------------- /lualib/comfun.lua: -------------------------------------------------------------------------------- 1 | --自己实现的功用函数 2 | 3 | local skynet = require "skynet" 4 | local log = require "log" 5 | 6 | local comfun = {} 7 | 8 | --number取整 9 | function comfun.get_int_part(x) 10 | if x < 0 then 11 | return math.ceil(x) 12 | end 13 | if math.ceil(x) == x then 14 | x = math.ceil(x) 15 | else 16 | x = math.ceil(x) - 1 17 | end 18 | return x 19 | end 20 | 21 | --外部请求处理 22 | function comfun.sock_handle(CMD, srv_name, cmd, fd, ...) 23 | local f = CMD[cmd] 24 | if f then 25 | local ret, msg_rsp_name, msg_rsp = f(fd, ...) 26 | skynet.send("watchdog", "lua", "socket", "send", fd, ret, msg_rsp_name, msg_rsp) 27 | else 28 | log.log("server_%s invalid_sock_cmd %s", srv_name, cmd) 29 | end 30 | end 31 | 32 | --内部请求处理 33 | function comfun.inner_handle(CMD, srv_name, cmd, ...) 34 | local f = CMD[cmd] 35 | if f then 36 | --内部接口调用全部返回 37 | skynet.ret(skynet.pack(f(...))) 38 | else 39 | log.log("service_%s invalid_inner_cmd %s", srv_name, cmd) 40 | end 41 | end 42 | 43 | --消息处理 44 | function comfun.dispatch(CMD, srv_name, cmd, subcom, ...) 45 | if cmd == "socket" then 46 | comfun.sock_handle(CMD, srv_name, subcom, ...) 47 | else 48 | comfun.inner_handle(CMD, srv_name, cmd, subcom, ...) 49 | end 50 | end 51 | 52 | --公用启动函数 53 | function comfun.srv_start(CMD, srv_name) 54 | skynet.start(function() 55 | skynet.dispatch("lua", function(_, _, cmd, subcom, ...) 56 | comfun.dispatch(CMD, srv_name, cmd, subcom, ...) 57 | end) 58 | 59 | if srv_name then 60 | skynet.register(srv_name) 61 | end 62 | end) 63 | end 64 | 65 | return comfun -------------------------------------------------------------------------------- /lualib/log.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local log = {} 4 | 5 | function log.log(format, ...) 6 | skynet.error(string.format(format, ...)) 7 | end 8 | 9 | return log -------------------------------------------------------------------------------- /lualib/protobuf.lua: -------------------------------------------------------------------------------- 1 | local c = require "protobuf.c" 2 | 3 | local setmetatable = setmetatable 4 | local type = type 5 | local table = table 6 | local assert = assert 7 | local pairs = pairs 8 | local ipairs = ipairs 9 | local string = string 10 | local print = print 11 | local io = io 12 | local tinsert = table.insert 13 | local rawget = rawget 14 | 15 | local M = {} 16 | 17 | local _pattern_cache = {} 18 | 19 | local P,GC 20 | 21 | P = debug.getregistry().PROTOBUF_ENV 22 | 23 | if P then 24 | GC = c._gc() 25 | else 26 | P= c._env_new() 27 | GC = c._gc(P) 28 | end 29 | 30 | M.GC = GC 31 | 32 | function M.lasterror() 33 | return c._last_error(P) 34 | end 35 | 36 | local decode_type_cache = {} 37 | local _R_meta = {} 38 | 39 | function _R_meta:__index(key) 40 | local v = decode_type_cache[self._CType][key](self, key) 41 | self[key] = v 42 | return v 43 | end 44 | 45 | local _reader = {} 46 | 47 | function _reader:real(key) 48 | return c._rmessage_real(self._CObj , key , 0) 49 | end 50 | 51 | function _reader:string(key) 52 | return c._rmessage_string(self._CObj , key , 0) 53 | end 54 | 55 | function _reader:bool(key) 56 | return c._rmessage_int(self._CObj , key , 0) ~= 0 57 | end 58 | 59 | function _reader:message(key, message_type) 60 | local rmessage = c._rmessage_message(self._CObj , key , 0) 61 | if rmessage then 62 | local v = { 63 | _CObj = rmessage, 64 | _CType = message_type, 65 | _Parent = self, 66 | } 67 | return setmetatable( v , _R_meta ) 68 | end 69 | end 70 | 71 | function _reader:int(key) 72 | return c._rmessage_int(self._CObj , key , 0) 73 | end 74 | 75 | function _reader:real_repeated(key) 76 | local cobj = self._CObj 77 | local n = c._rmessage_size(cobj , key) 78 | local ret = {} 79 | for i=0,n-1 do 80 | tinsert(ret, c._rmessage_real(cobj , key , i)) 81 | end 82 | return ret 83 | end 84 | 85 | function _reader:string_repeated(key) 86 | local cobj = self._CObj 87 | local n = c._rmessage_size(cobj , key) 88 | local ret = {} 89 | for i=0,n-1 do 90 | tinsert(ret, c._rmessage_string(cobj , key , i)) 91 | end 92 | return ret 93 | end 94 | 95 | function _reader:bool_repeated(key) 96 | local cobj = self._CObj 97 | local n = c._rmessage_size(cobj , key) 98 | local ret = {} 99 | for i=0,n-1 do 100 | tinsert(ret, c._rmessage_int(cobj , key , i) ~= 0) 101 | end 102 | return ret 103 | end 104 | 105 | function _reader:message_repeated(key, message_type) 106 | local cobj = self._CObj 107 | local n = c._rmessage_size(cobj , key) 108 | local ret = {} 109 | for i=0,n-1 do 110 | local m = { 111 | _CObj = c._rmessage_message(cobj , key , i), 112 | _CType = message_type, 113 | _Parent = self, 114 | } 115 | tinsert(ret, setmetatable( m , _R_meta )) 116 | end 117 | return ret 118 | end 119 | 120 | function _reader:int_repeated(key) 121 | local cobj = self._CObj 122 | local n = c._rmessage_size(cobj , key) 123 | local ret = {} 124 | for i=0,n-1 do 125 | tinsert(ret, c._rmessage_int(cobj , key , i)) 126 | end 127 | return ret 128 | end 129 | 130 | --[[ 131 | #define PBC_INT 1 132 | #define PBC_REAL 2 133 | #define PBC_BOOL 3 134 | #define PBC_ENUM 4 135 | #define PBC_STRING 5 136 | #define PBC_MESSAGE 6 137 | #define PBC_FIXED64 7 138 | #define PBC_FIXED32 8 139 | #define PBC_BYTES 9 140 | #define PBC_INT64 10 141 | #define PBC_UINT 11 142 | #define PBC_UNKNOWN 12 143 | #define PBC_REPEATED 128 144 | ]] 145 | 146 | _reader[1] = function(msg) return _reader.int end 147 | _reader[2] = function(msg) return _reader.real end 148 | _reader[3] = function(msg) return _reader.bool end 149 | _reader[4] = function(msg) return _reader.string end 150 | _reader[5] = function(msg) return _reader.string end 151 | _reader[6] = function(msg) 152 | local message = _reader.message 153 | return function(self,key) 154 | return message(self, key, msg) 155 | end 156 | end 157 | _reader[7] = _reader[1] 158 | _reader[8] = _reader[1] 159 | _reader[9] = _reader[5] 160 | _reader[10] = _reader[7] 161 | _reader[11] = _reader[7] 162 | 163 | _reader[128+1] = function(msg) return _reader.int_repeated end 164 | _reader[128+2] = function(msg) return _reader.real_repeated end 165 | _reader[128+3] = function(msg) return _reader.bool_repeated end 166 | _reader[128+4] = function(msg) return _reader.string_repeated end 167 | _reader[128+5] = function(msg) return _reader.string_repeated end 168 | _reader[128+6] = function(msg) 169 | local message = _reader.message_repeated 170 | return function(self,key) 171 | return message(self, key, msg) 172 | end 173 | end 174 | _reader[128+7] = _reader[128+1] 175 | _reader[128+8] = _reader[128+1] 176 | _reader[128+9] = _reader[128+5] 177 | _reader[128+10] = _reader[128+7] 178 | _reader[128+11] = _reader[128+7] 179 | 180 | local _decode_type_meta = {} 181 | 182 | function _decode_type_meta:__index(key) 183 | local t, msg = c._env_type(P, self._CType, key) 184 | local func = assert(_reader[t],key)(msg) 185 | self[key] = func 186 | return func 187 | end 188 | 189 | setmetatable(decode_type_cache , { 190 | __index = function(self, key) 191 | local v = setmetatable({ _CType = key } , _decode_type_meta) 192 | self[key] = v 193 | return v 194 | end 195 | }) 196 | 197 | local function decode_message( message , buffer, length) 198 | local rmessage = c._rmessage_new(P, message, buffer, length) 199 | if rmessage then 200 | local self = { 201 | _CObj = rmessage, 202 | _CType = message, 203 | } 204 | c._add_rmessage(GC,rmessage) 205 | return setmetatable( self , _R_meta ) 206 | end 207 | end 208 | 209 | ----------- encode ---------------- 210 | 211 | local encode_type_cache = {} 212 | 213 | local function encode_message(CObj, message_type, t) 214 | local type = encode_type_cache[message_type] 215 | for k,v in pairs(t) do 216 | local func = type[k] 217 | func(CObj, k , v) 218 | end 219 | end 220 | 221 | local _writer = { 222 | real = c._wmessage_real, 223 | enum = c._wmessage_string, 224 | string = c._wmessage_string, 225 | int = c._wmessage_int, 226 | } 227 | 228 | function _writer:bool(k,v) 229 | c._wmessage_int(self, k, v and 1 or 0) 230 | end 231 | 232 | function _writer:message(k, v , message_type) 233 | local submessage = c._wmessage_message(self, k) 234 | encode_message(submessage, message_type, v) 235 | end 236 | 237 | function _writer:real_repeated(k,v) 238 | for _,v in ipairs(v) do 239 | c._wmessage_real(self,k,v) 240 | end 241 | end 242 | 243 | function _writer:bool_repeated(k,v) 244 | for _,v in ipairs(v) do 245 | c._wmessage_int(self, k, v and 1 or 0) 246 | end 247 | end 248 | 249 | function _writer:string_repeated(k,v) 250 | for _,v in ipairs(v) do 251 | c._wmessage_string(self,k,v) 252 | end 253 | end 254 | 255 | function _writer:message_repeated(k,v, message_type) 256 | for _,v in ipairs(v) do 257 | local submessage = c._wmessage_message(self, k) 258 | encode_message(submessage, message_type, v) 259 | end 260 | end 261 | 262 | function _writer:int_repeated(k,v) 263 | for _,v in ipairs(v) do 264 | c._wmessage_int(self,k,v) 265 | end 266 | end 267 | 268 | _writer[1] = function(msg) return _writer.int end 269 | _writer[2] = function(msg) return _writer.real end 270 | _writer[3] = function(msg) return _writer.bool end 271 | _writer[4] = function(msg) return _writer.string end 272 | _writer[5] = function(msg) return _writer.string end 273 | _writer[6] = function(msg) 274 | local message = _writer.message 275 | return function(self,key , v) 276 | return message(self, key, v, msg) 277 | end 278 | end 279 | _writer[7] = _writer[1] 280 | _writer[8] = _writer[1] 281 | _writer[9] = _writer[5] 282 | _writer[10] = _writer[7] 283 | _writer[11] = _writer[7] 284 | 285 | _writer[128+1] = function(msg) return _writer.int_repeated end 286 | _writer[128+2] = function(msg) return _writer.real_repeated end 287 | _writer[128+3] = function(msg) return _writer.bool_repeated end 288 | _writer[128+4] = function(msg) return _writer.string_repeated end 289 | _writer[128+5] = function(msg) return _writer.string_repeated end 290 | _writer[128+6] = function(msg) 291 | local message = _writer.message_repeated 292 | return function(self,key, v) 293 | return message(self, key, v, msg) 294 | end 295 | end 296 | 297 | _writer[128+7] = _writer[128+1] 298 | _writer[128+8] = _writer[128+1] 299 | _writer[128+9] = _writer[128+5] 300 | _writer[128+10] = _writer[128+7] 301 | _writer[128+11] = _writer[128+7] 302 | 303 | local _encode_type_meta = {} 304 | 305 | function _encode_type_meta:__index(key) 306 | local t, msg = c._env_type(P, self._CType, key) 307 | local func = assert(_writer[t],key)(msg) 308 | self[key] = func 309 | return func 310 | end 311 | 312 | setmetatable(encode_type_cache , { 313 | __index = function(self, key) 314 | local v = setmetatable({ _CType = key } , _encode_type_meta) 315 | self[key] = v 316 | return v 317 | end 318 | }) 319 | 320 | function M.encode( message, t , func , ...) 321 | local encoder = c._wmessage_new(P, message) 322 | assert(encoder , message) 323 | encode_message(encoder, message, t) 324 | if func then 325 | local buffer, len = c._wmessage_buffer(encoder) 326 | local ret = func(buffer, len, ...) 327 | c._wmessage_delete(encoder) 328 | return ret 329 | else 330 | local s = c._wmessage_buffer_string(encoder) 331 | c._wmessage_delete(encoder) 332 | return s 333 | end 334 | end 335 | 336 | --------- unpack ---------- 337 | 338 | local _pattern_type = { 339 | [1] = {"%d","i"}, 340 | [2] = {"%F","r"}, 341 | [3] = {"%d","b"}, 342 | [5] = {"%s","s"}, 343 | [6] = {"%s","m"}, 344 | [7] = {"%D","d"}, 345 | [128+1] = {"%a","I"}, 346 | [128+2] = {"%a","R"}, 347 | [128+3] = {"%a","B"}, 348 | [128+5] = {"%a","S"}, 349 | [128+6] = {"%a","M"}, 350 | [128+7] = {"%a","D"}, 351 | } 352 | 353 | _pattern_type[4] = _pattern_type[1] 354 | _pattern_type[8] = _pattern_type[1] 355 | _pattern_type[9] = _pattern_type[5] 356 | _pattern_type[10] = _pattern_type[7] 357 | _pattern_type[11] = _pattern_type[7] 358 | _pattern_type[128+4] = _pattern_type[128+1] 359 | _pattern_type[128+8] = _pattern_type[128+1] 360 | _pattern_type[128+9] = _pattern_type[128+5] 361 | _pattern_type[128+10] = _pattern_type[128+7] 362 | _pattern_type[128+11] = _pattern_type[128+7] 363 | 364 | 365 | local function _pattern_create(pattern) 366 | local iter = string.gmatch(pattern,"[^ ]+") 367 | local message = iter() 368 | local cpat = {} 369 | local lua = {} 370 | for v in iter do 371 | local tidx = c._env_type(P, message, v) 372 | local t = _pattern_type[tidx] 373 | assert(t,tidx) 374 | tinsert(cpat,v .. " " .. t[1]) 375 | tinsert(lua,t[2]) 376 | end 377 | local cobj = c._pattern_new(P, message , "@" .. table.concat(cpat," ")) 378 | if cobj == nil then 379 | return 380 | end 381 | c._add_pattern(GC, cobj) 382 | local pat = { 383 | CObj = cobj, 384 | format = table.concat(lua), 385 | size = 0 386 | } 387 | pat.size = c._pattern_size(pat.format) 388 | 389 | return pat 390 | end 391 | 392 | setmetatable(_pattern_cache, { 393 | __index = function(t, key) 394 | local v = _pattern_create(key) 395 | t[key] = v 396 | return v 397 | end 398 | }) 399 | 400 | function M.unpack(pattern, buffer, length) 401 | local pat = _pattern_cache[pattern] 402 | return c._pattern_unpack(pat.CObj , pat.format, pat.size, buffer, length) 403 | end 404 | 405 | function M.pack(pattern, ...) 406 | local pat = _pattern_cache[pattern] 407 | return c._pattern_pack(pat.CObj, pat.format, pat.size , ...) 408 | end 409 | 410 | function M.check(typename , field) 411 | if field == nil then 412 | return c._env_type(P,typename) 413 | else 414 | return c._env_type(P,typename,field) ~=0 415 | end 416 | end 417 | 418 | -------------- 419 | 420 | local default_cache = {} 421 | 422 | -- todo : clear default_cache, v._CObj 423 | 424 | local function default_table(typename) 425 | local v = default_cache[typename] 426 | if v then 427 | return v 428 | end 429 | 430 | v = { __index = assert(decode_message(typename , "")) } 431 | 432 | default_cache[typename] = v 433 | return v 434 | end 435 | 436 | local decode_message_mt = {} 437 | 438 | local function decode_message_cb(typename, buffer) 439 | return setmetatable ( { typename, buffer } , decode_message_mt) 440 | end 441 | 442 | function M.decode(typename, buffer, length) 443 | local ret = {} 444 | local ok = c._decode(P, decode_message_cb , ret , typename, buffer, length) 445 | if ok then 446 | return setmetatable(ret , default_table(typename)) 447 | else 448 | return false , c._last_error(P) 449 | end 450 | end 451 | 452 | local function expand(tbl) 453 | local typename = rawget(tbl , 1) 454 | local buffer = rawget(tbl , 2) 455 | tbl[1] , tbl[2] = nil , nil 456 | assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename) 457 | setmetatable(tbl , default_table(typename)) 458 | end 459 | 460 | function decode_message_mt.__index(tbl, key) 461 | expand(tbl) 462 | return tbl[key] 463 | end 464 | 465 | function decode_message_mt.__pairs(tbl) 466 | expand(tbl) 467 | return pairs(tbl) 468 | end 469 | 470 | local function set_default(typename, tbl) 471 | for k,v in pairs(tbl) do 472 | if type(v) == "table" then 473 | local t, msg = c._env_type(P, typename, k) 474 | if t == 6 then 475 | set_default(msg, v) 476 | elseif t == 128+6 then 477 | for _,v in ipairs(v) do 478 | set_default(msg, v) 479 | end 480 | end 481 | end 482 | end 483 | return setmetatable(tbl , default_table(typename)) 484 | end 485 | 486 | function M.register(buffer) 487 | c._env_register(P, buffer) 488 | end 489 | 490 | function M.register_file(filename) 491 | local f = assert(io.open(filename , "rb")) 492 | local buffer = f:read "*a" 493 | c._env_register(P, buffer) 494 | f:close() 495 | end 496 | 497 | function M.enum_id(enum_type, enum_name) 498 | return c._env_enum_id(P, enum_type, enum_name) 499 | end 500 | 501 | function M.extract(tbl) 502 | local typename = rawget(tbl , 1) 503 | local buffer = rawget(tbl , 2) 504 | if type(typename) == "string" and type(buffer) == "string" then 505 | if M.check(typename) then 506 | expand(tbl) 507 | end 508 | end 509 | 510 | for k, v in pairs(tbl) do 511 | if type(v) == "table" then 512 | M.extract(v) 513 | end 514 | end 515 | end 516 | 517 | M.default=set_default 518 | 519 | return M 520 | -------------------------------------------------------------------------------- /lualib/protopack.lua: -------------------------------------------------------------------------------- 1 | --pb数据的序列化与反序列化 2 | 3 | local utils = require "utils" 4 | local skynet = require "skynet" 5 | local retcode = require "retcode" 6 | 7 | local M = {} 8 | 9 | function M.pack(ret, name, msg) 10 | --pb协议头 11 | local ret = ret or 0 12 | local msg_head = { 13 | msgtype = 2, 14 | msgname = name, 15 | msgret = ret 16 | } 17 | local buf_head = skynet.call(M.pbc, "lua", "encode", "PbHead.MsgHead", msg_head) 18 | 19 | print("+++++++++++++++pack") 20 | utils.print(msg_head) 21 | utils.print(msg) 22 | 23 | --pb协议数据 24 | local len 25 | local pack 26 | if ret == 0 then 27 | local buf_body = skynet.call(M.pbc, "lua", "encode", name, msg) 28 | len = 2 + #buf_head + 2 + #buf_body + 1 29 | pack = string.pack(">Hs2s2c1", len, buf_head, buf_body, 't') 30 | else 31 | --返回码不为0时,只下发pb协议头 32 | len = 2 + #buf_head + 1 33 | pack = string.pack(">Hs2s1", len, buf_head, 't') 34 | end 35 | 36 | return pack 37 | end 38 | 39 | function M.unpack(data) 40 | print("---------------Unpack") 41 | local buf_head, buf_body, ch_end = string.unpack(">s2s2c1", data) 42 | local msg_head = skynet.call(M.pbc, "lua", "decode", "PbHead.MsgHead", buf_head) 43 | local msg_body = skynet.call(M.pbc, "lua", "decode", msg_head.msgname, buf_body) 44 | utils.print(msg_head) 45 | utils.print(msg_body) 46 | return msg_head.msgname, msg_body 47 | end 48 | 49 | return M -------------------------------------------------------------------------------- /lualib/retcode.lua: -------------------------------------------------------------------------------- 1 | --给客户端请求的返回码 2 | 3 | local ret_arr = { 4 | OK = 0, --成功 5 | 6 | --登录 7 | LOGIN_GUEST_REGISTER_FAIL = 201, --游客用户创建失败 8 | LOGIN_PLATFORM_ERROR = 202, --平台编号错误 9 | 10 | --创建房间 11 | ROOM_CREATE_FAIL = 211, --创建房间失败 12 | ROOM_CREATE_IN_ROOM = 212, --在房间内 13 | ROOM_HAD_CREATE= 213, --已经创建了房间 14 | 15 | --进入房间 16 | ROOM_ENTER_NUM_NOT_EXIST = 221, --房间号不存在 17 | ROOM_ENTER_NOT_OPEN = 222, --房间未开启 18 | ROOM_ENTER_NO_POSITION = 223, --房间已满 19 | ROOM_ENTER_HAD_START = 224, --牌局已经开始,不能进入房间 20 | ROOM_ENTER_IN_OTHER_ROOM = 225, --已经在其它房间内 21 | ROOM_ENTER_IN_THIS_ROOM = 226, --已经在此房间内 22 | 23 | --离开房间 24 | ROOM_LEAVE_HAVE_NO_ROOM = 241, --没有房间 25 | ROOM_LEAVE_IN_OTHER_ROOM = 242, --在其它房间 26 | ROOM_LEAVE_NOT_IN_ROOM = 243, --不在此房间 27 | ROOM_LEAVE_HAD_START = 244, --牌局已经开始,不能离开房间 28 | 29 | 30 | --解散房间 31 | ROOM_DISSOLVE_NOT_OWNER = 251, --不是房主 32 | 33 | --准备 34 | ROOM_READY_HAVE_NO_ROOM = 261, --没有房间 35 | ROOM_READY_NUM_NOT_EXIST = 262, --房间号不存在 36 | ROOM_READY_NOT_IN_ROOM = 263, --不在房间内 37 | ROOM_READY_IN_OTHER_ROOM = 264, --在其它房间 38 | ROOM_READY_HAD_READY = 265, --已经准备 39 | } 40 | 41 | return ret_arr -------------------------------------------------------------------------------- /lualib/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local function serialize(obj) 4 | local lua = "" 5 | local t = type(obj) 6 | if t == "number" then 7 | lua = lua .. obj 8 | elseif t == "boolean" then 9 | lua = lua .. tostring(obj) 10 | elseif t == "string" then 11 | lua = lua .. string.format("%q", obj) 12 | elseif t == "table" then 13 | lua = lua .. "{\n" 14 | for k, v in pairs(obj) do 15 | lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n" 16 | end 17 | local metatable = getmetatable(obj) 18 | if metatable ~= nil and type(metatable.__index) == "table" then 19 | for k, v in pairs(metatable.__index) do 20 | lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n" 21 | end 22 | end 23 | lua = lua .. "}" 24 | elseif t == "nil" then 25 | return "nil" 26 | elseif t == "userdata" then 27 | return "userdata" 28 | elseif t == "function" then 29 | return "function" 30 | else 31 | error("can not serialize a " .. t .. " type.") 32 | end 33 | return lua 34 | end 35 | 36 | function M.print(...) 37 | local t = {...} 38 | local ret = {} 39 | for _,v in pairs(t) do 40 | table.insert(ret, serialize(v)) 41 | end 42 | print(table.concat(ret, ", ")) 43 | end 44 | 45 | function M.split(str, delimiter) 46 | if str == nil or str == '' or delimiter == nil then 47 | return nil 48 | end 49 | 50 | local result = {} 51 | for match in (str..delimiter):gmatch("(.-)"..delimiter) do 52 | table.insert(result, match) 53 | end 54 | return result 55 | end 56 | 57 | function M.hex(str) 58 | local len = #str 59 | local ret = "" 60 | for i=1,len do 61 | local c = tonumber(str:byte(i)) 62 | local cstr = string.format("%02X ", c) 63 | ret = ret .. cstr 64 | end 65 | print(ret) 66 | end 67 | 68 | return M -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | all: proto/pbhead.pb proto/pblogin.pb proto/pbroom.pb 3 | 4 | proto/pbhead.pb: proto/pbhead.proto 5 | protoc --descriptor_set_out proto/pbhead.pb proto/pbhead.proto 6 | 7 | proto/pblogin.pb: proto/pblogin.proto 8 | protoc --descriptor_set_out proto/pblogin.pb proto/pblogin.proto 9 | 10 | proto/pbroom.pb: proto/pbroom.proto 11 | protoc --descriptor_set_out proto/pbroom.pb proto/pbroom.proto -------------------------------------------------------------------------------- /proto/pbhead.pb: -------------------------------------------------------------------------------- 1 | 2 | S 3 | pbhead.protoPbHead"; 4 | MsgHead 5 | msgtype ( 6 | msgname (  7 | msgret ( -------------------------------------------------------------------------------- /proto/pbhead.proto: -------------------------------------------------------------------------------- 1 | //协议头 2 | package PbHead; 3 | 4 | message MsgHead{ 5 | required int32 msgtype = 1; //协议数据类型 1表示请求包 2表示响应包 3 推送包 6 | required string msgname = 2; //协议结构名 7 | required int32 msgret = 3; //通讯协议出错码 只用在响应包中 非0表示出错 出错情况下没有PBBody 8 | } -------------------------------------------------------------------------------- /proto/pblogin.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytemode/skynet_pbc/387da1a1d988d3cca9400d140fa4e120c1fedc04/proto/pblogin.pb -------------------------------------------------------------------------------- /proto/pblogin.proto: -------------------------------------------------------------------------------- 1 | //登录 2 | 3 | package PbLogin; 4 | 5 | //请求登录 6 | message MsgLoginReq{ 7 | required int32 platform = 1; //平台编号 8 | required string user_id = 2; //用户Id 9 | } 10 | 11 | //登录返回 12 | message MsgLoginRsp{ 13 | required int32 platform = 1; 14 | required string user_id = 2; 15 | required int32 char_id = 3; //角色Id 16 | required string char_name = 4; //角色名 17 | } -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | $(pwd)/skynet/skynet config 4 | -------------------------------------------------------------------------------- /service/main.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | 3 | local max_client = 10240 4 | 5 | skynet.start(function() 6 | skynet.error("Server start") 7 | 8 | skynet.newservice("console") 9 | skynet.newservice("debug_console", 8000) 10 | 11 | local watchdog = skynet.uniqueservice("watchdog") 12 | skynet.call(watchdog, "lua", "start", { 13 | port = 5000, 14 | maxclient = max_client, 15 | nodelay = true, 16 | }) 17 | skynet.error("watchdog Listen on", 5000) 18 | 19 | --service = skynet.newservice("mongodb") 20 | --skynet.send(service, "lua", "init") 21 | 22 | skynet.exit() 23 | end) -------------------------------------------------------------------------------- /service/pbc.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | require "skynet.manager" 3 | local utils = require "utils" 4 | local protobuf = require "protobuf" 5 | 6 | local pb_files = { 7 | "./proto/pbhead.pb", 8 | "./proto/pblogin.pb", 9 | } 10 | 11 | local cmd = {} 12 | 13 | function cmd.init() 14 | for _,v in ipairs(pb_files) do 15 | utils.print(protobuf.register_file(v)) 16 | end 17 | end 18 | 19 | function cmd.encode(msg_name, msg) 20 | skynet.error("encode"..msg_name) 21 | return protobuf.encode(msg_name, msg) 22 | end 23 | 24 | function cmd.decode(msg_name, data) 25 | skynet.error("decode ".. msg_name.. " " .. type(data) .." " .. #data) 26 | return protobuf.decode(msg_name, data) 27 | end 28 | 29 | function cmd.test() 30 | skynet.error("pbc test...") 31 | local msg = {account = "name"} 32 | utils.print("msg = ",msg) 33 | skynet.error("encode") 34 | local data = cmd.encode("Login.Login", msg) 35 | skynet.error("decode"..#(data)) 36 | local de_msg = cmd.decode("Login.Login", data) 37 | skynet.error(de_msg.account) 38 | end 39 | 40 | skynet.start(function () 41 | skynet.error("init pbc...") 42 | cmd.init() 43 | 44 | skynet.dispatch("lua", function (session, address, command, ...) 45 | local f = cmd[command] 46 | if not f then 47 | skynet.ret(skynet.pack(nil, "Invalid command" .. command)) 48 | end 49 | 50 | if command == "decode" then 51 | local name 52 | local buf 53 | name,buf = ... 54 | skynet.ret(skynet.pack(cmd.decode(name,buf))) 55 | return 56 | end 57 | local ret = f(...) 58 | skynet.ret(skynet.pack(ret)) 59 | end) 60 | end) 61 | -------------------------------------------------------------------------------- /service/sockhandler.lua: -------------------------------------------------------------------------------- 1 | --客户端请求处理,负责客户端请求的分发 2 | 3 | local skynet = require "skynet" 4 | local utils = require "utils" 5 | 6 | local funs = {} 7 | local login 8 | local agentmgr 9 | local roommgr 10 | 11 | local handler_arr = { 12 | ["PbLogin.MsgLoginReq"] = function(...) funs.login_req(...) end, 13 | } 14 | 15 | -------------------------------------------------------------------------------- 16 | 17 | --登录 18 | function funs.login_req(fd, msg) 19 | --skynet.send(login, "lua", "socket", "login", fd, msg) 20 | local MsgLoginRsp = { 21 | platform = 1, 22 | user_id = "fdasfad", 23 | char_id = 1111, 24 | char_name = "dsfa" 25 | } 26 | skynet.send("watchdog", "lua", "socket", "send", fd, 0, "PbLogin.MsgLoginRsp", MsgLoginRsp) 27 | end 28 | 29 | --创建房间 30 | function funs.room_create_req(fd, msg) 31 | skynet.send(roommgr, "lua", "socket", "create", fd, msg) 32 | end 33 | 34 | --进入房间 35 | function funs.room_enter_req(fd, msg) 36 | skynet.send(roommgr, "lua", "socket", "enter", fd, msg) 37 | end 38 | 39 | -------------------------------------------------------------------------------- 40 | 41 | local CMD = {} 42 | 43 | function CMD.init() 44 | --login = skynet.uniqueservice("login") 45 | --roommgr = skynet.uniqueservice("roommgr") 46 | --agentmgr = skynet.uniqueservice("agentmgr") 47 | end 48 | 49 | --根据协议名,调用对用处理函数 50 | function CMD.handle(fd, msg_name, msg) 51 | local f = handler_arr[msg_name] 52 | f(fd, msg) 53 | end 54 | 55 | -------------------------------------------------------------------------------- 56 | 57 | skynet.start(function() 58 | CMD.init() 59 | 60 | skynet.dispatch("lua", function(_, _, cmd, ...) 61 | local f = CMD[cmd] 62 | if f then 63 | f(...) 64 | else 65 | log.log("service_clienthandler invalid_cmd %s", cmd) 66 | end 67 | end) 68 | end) -------------------------------------------------------------------------------- /service/watchdog.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local log = require "log" 3 | local protopack = require "protopack" 4 | local socket = require "socket" 5 | local utils = require "utils" 6 | require "skynet.manager" 7 | 8 | local gate 9 | local SOCKET = {} 10 | local pbc 11 | local sock_handler 12 | local redissrv 13 | 14 | -------------------------------------------------------------------------------- 15 | function SOCKET.open(fd, addr) 16 | log.log("New client from : %s", addr) 17 | skynet.call(gate, "lua", "accept", fd) 18 | end 19 | 20 | function SOCKET.close(fd) 21 | log.log("socket close fd=%d", fd) 22 | end 23 | 24 | function SOCKET.error(fd, msg) 25 | log.log("socket error fd = %d msg=%s", fd, msg) 26 | end 27 | 28 | function SOCKET.warning(fd, size) 29 | -- size K bytes havn't send out in fd 30 | log.log("socket warning fd=%d size=%d", fd, size) 31 | end 32 | 33 | function SOCKET.data(fd, data) 34 | local name, msg = protopack.unpack(data) 35 | skynet.send(sock_handler, "lua", "handle", fd, name, msg) 36 | end 37 | 38 | function SOCKET.send(fd, ret, name, msg) 39 | local data = protopack.pack(ret, name, msg) 40 | socket.write(fd, data) 41 | end 42 | 43 | -------------------------------------------------------------------------------- 44 | 45 | local CMD = {} 46 | function CMD.start(conf) 47 | skynet.call(gate, "lua", "open", conf) 48 | pbc = skynet.uniqueservice("pbc") 49 | protopack.pbc = pbc 50 | sock_handler = skynet.uniqueservice("sockhandler") 51 | --redissrv = skynet.uniqueservice("redissrv") 52 | end 53 | 54 | function CMD.close(fd) 55 | end 56 | 57 | -------------------------------------------------------------------------------- 58 | 59 | skynet.start(function() 60 | skynet.dispatch("lua", function(_, _, cmd, subcmd, ...) 61 | if cmd == "socket" then 62 | local f = SOCKET[subcmd] 63 | f(...) 64 | else 65 | local f = assert(CMD[cmd]) 66 | skynet.ret(skynet.pack(f(subcmd, ...))) 67 | end 68 | end) 69 | 70 | gate = skynet.newservice("gate") 71 | skynet.register("watchdog") 72 | end) --------------------------------------------------------------------------------