zoukankan      html  css  js  c++  java
  • skynet之使用sproto

        sproto的简介略过,这里直接上代码,新建proto.lua文件,内容如下:

    local sprotoparser = require "sprotoparser"

    local proto = {}

    proto.c2s = sprotoparser.parse [[
    .package {
        type 0 : integer
        session 1 : integer
    }

    handshake 1 {
        response {
            msg 0 : string
        }
    }

    say 2 {
        request {
            name 0 : string
            msg 1 : string
        }
    }

    quit 3 {}

    ]]

    proto.s2c = sprotoparser.parse [[
    .package {
        type 0 : integer
        session 1 : integer
    }

    heartbeat 1 {}
    ]]

    return proto

    新建client1.lua文件,内容如下:

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

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

    local socket = require "client.socket"

    --
    通信协议

    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_request(name, args)
        session = session + 1
        local str = request(name, args, session)

        --
    解包测试
        -- local host2 = sproto.new(proto.c2s):host "package"
        -- local type,str2 = host2:dispatch(str)
        -- print(type)
        -- print(str2)

        socket.send(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"
    require "skynet.manager"    -- import skynet.register
    local socket = require "skynet.socket"

    local proto = require "proto"
    local sproto = require "sproto"

    local host

    local REQUEST = {}

    function REQUEST:say()
        print("say", self.name, self.msg)
    end

    function REQUEST:handshake()
        print("handshake")
    end

    function REQUEST:quit()
        print("quit")
    end

    local function request(name, args, response)
        local f = assert(REQUEST[name])
        local r = f(args)
        if response then
            --
    生成回应包
    (response是一个用于生成回应包的函数。)
            --
    处理session对应问题
            -- return response(r)
        end
    end

    local function send_package(fd,pack)
        --
    协议与客户端对应(两字节长度包头+内容)
        local package = string.pack(">s2", pack)
        socket.write(fd, package)
    end

    local function accept(id)
        --
    每当 accept 函数获得一个新的 socket id 后,并不会立即收到这个 socket 上的数据。这是因为,我们有时会希望把这个 socket 的操作权转让给别的服务去处理。
        --
    任何一个服务只有在调用 socket.start(id) 之后,才可以收到这个 socket 上的数据。

        socket.start(id)

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

        while true do
            local str = socket.read(id)
            if str then
                local type,str2,str3,str4 = host:dispatch(str)

                if type=="REQUEST" then
                    -- REQUEST :
    第一个返回值为 "REQUEST" 时,表示这是一个远程请求。如果请求包中没有 session 字段,表示该请求不需要回应。这时,第 2 和第 3 个返回值分别为消息类型名(即在 sproto 定义中提到的某个以 . 开头的类型名),以及消息内容(通常是一个 table );如果请求包中有 session 字段,那么还会有第 4 个返回值:一个用于生成回应包的函数。
                    local ok, result = pcall(request, str2,str3,str4)

                    if ok then
                        if result then
                            socket.write(id, "
    收到了
    ")
                            --
    暂时不使用回应包回应

                            -- print("response:"..result)
                            -- send_package(id,result)
                        end
                    else
                        skynet.error(result)
                    end
                end

                if type=="RESPONSE" then
                    -- RESPONSE
    :第一个返回值为 "RESPONSE" 时,第 2 3 个返回值分别为 session 和消息内容。消息内容通常是一个 table ,但也可能不存在内容(仅仅是一个回应确认)。
                    --
    暂时不处理客户端的回应
                    print("client response")
                end        

            else
                socket.close(id)
                return
            end
        end
    end

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

        socket.start(id , function(id, addr)
                --
    接收到客户端连接或发送消息()
                print("connect from " .. addr .. " " .. id)

                --
    处理接收到的消息
                accept(id)
            end)
        --
    可以为自己注册一个别名。(别名必须在 32 个字符以内)
        skynet.register "SOCKET1"
    end)

     

     

     

     

     

     

     

  • 相关阅读:
    jquery全屏幻灯轮播焦点图
    PHP curl 上传文件版本兼容问题
    一个网站同一域名不同目录下的文件访问到的cookie值不同是什么原因?
    Linux系统查找清理磁盘大文件方法
    REDIS常用命令
    CentOS 6.4安装pip,CentOS安装python包管理安装工具pip的方法
    centos6 编译安装nodejs4.3
    centos yum安装php5.6.19 remi源按照
    Mac下用brew搭建PHP(LNMP/LAMP)开发环境
    为什么JAVA要提供 wait/notify 机制?是为了避免轮询带来的性能损失
  • 原文地址:https://www.cnblogs.com/skiing886/p/7805254.html
Copyright © 2011-2022 走看看