【轉】從零開始學習Skynet_examples研究


轉自 http://blog.csdn.net/mr_virus/article/details/52330193

一、編譯Skynet:

1、用ubuntu15.10直接

make linux

編譯Skynet會有報錯。安裝autoconf、libreadline6、libreadline6-dev后就能編譯成功了。

sudo apt-get install autoconf  

sudo apt-get install libreadline6 libreadline6-dev  


二、關於examples相關的代碼分析:

1、關於examples/config里面有一行:

start = "main"  -- main script  

意思是通過start="main"開啟第一個Skynet的服務main.lua。這個文件main.lua也在examples文件夾中:

local skynet = require "skynet"  
local sprotoloader = require "sprotoloader"  
  
local max_client = 64  
  
skynet.start(function()  
    skynet.error("Server start")  
    skynet.uniqueservice("protoloader")  
    if not skynet.getenv "daemon" then  
        local console = skynet.newservice("console")  
    end  
    skynet.newservice("debug_console",8000)  
    skynet.newservice("simpledb")  
    local watchdog = skynet.newservice("watchdog")  
    skynet.call(watchdog, "lua", "start", {  
        port = 8888,  
        maxclient = max_client,  
        nodelay = true,  
    })  
    skynet.error("Watchdog listen on", 8888)  
    skynet.exit()  
end)  

  

第一行先引用skynet這個庫,這個庫是用lua寫的,即是lualib/skynet.lua。里面定義了這些接口:

 

1).skynet.start()用於服務的入口,加載lua服務時先運行這里的代碼,它調用了luaclib-src/lua_skynet.c里面的callback(),最終調用skynet的框架skynet_callback()來設置毀掉函數。

2).skynet.newservice()用於啟動一個lua寫的服務,省略掉.lua后綴名。它調用了skynet.call()然后skynet.call()調用luaclib-src/lua_skynet.c里面send(),最終調用skynet的框架skynet_send()壓入隊列。

3).skynet.call()用於發送一條消息給Skynet的框架。消息會壓入隊列,等待SKynet框架的調度。

4).skynet.exit()移除服務,通過skynet.send()發送一條消息給skynet框架來移除lua的這個服務。

5).skynet.monitor()用於監視服務,看它是否關閉。

main.lua共打開了四個服務:

1).service_mgr:這個是系統的模塊,用於管理服務。

2).console:這個是系統的模塊,用於管理輸出。

3).simpledb:這個是例子模塊,用於管理Key-Value數據。

4).watchdog:這個是例子模塊,用於監視socket端口,等待數據。

main.lua沒有調用其他函數,加載完服務,它也就完成了任務,所以它最后調用了skynet.exit()把自己殺掉。

現在Skynet已經啟動了watchdog服務,監聽着8888端口,等待客戶端的連接。

下面是watchdog服務的skynet_start()開始函數:

skynet.start(function()  
    skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)  
        if cmd == "socket" then  
            local f = SOCKET[subcmd]  
            f(...)  
            -- socket api don't need return  
        else  
            local f = assert(CMD[cmd])  
            skynet.ret(skynet.pack(f(subcmd, ...)))  
        end  
    end)  
  
    gate = skynet.newservice("gate")  
end)

skynet.dispatch()這個服務的回調函數,通過SOCKET[]來調用函數,這些函數有:

 

SOCKET.open():打開agent服務並啟動,使用gate來管理socket。

SOCKET.close():關閉agent服務。

SOCKET.error():打印錯誤信息。

SOCKET.data():有數據到來。
下面是agent服務代碼:

function CMD.start(conf)  
    local fd = conf.client  
    local gate = conf.gate  
    WATCHDOG = conf.watchdog  
    -- slot 1,2 set at main.lua  
    host = sprotoloader.load(1):host "package"  
    send_request = host:attach(sprotoloader.load(2))  
    skynet.fork(function()  
        while true do  
            send_package(send_request "heartbeat")  
            skynet.sleep(500)  
        end  
    end)  

  client_fd = fd
  skynet.call(gate,"lua","forward",fd)
end
 
 
skynet.start(function()  
<span style="white-space:pre">    </span>skynet.dispatch("lua", function(_,_, command, ...)  
<span style="white-space:pre">        </span>local f = CMD[command]  
<span style="white-space:pre">        </span>skynet.ret(skynet.pack(f(...)))  
<span style="white-space:pre">    </span>end)  
end)  

前面watchdog調用SOCK.open()的時候就調用了這里的CMD.start(),在客戶端輸出了"Welcome to skynet"。

Agent的核心就是注冊了協議,並根據協議把數據發送給simpledb服務去處理。

 
skynet.register_protocol {  
    name = "client",  
    id = skynet.PTYPE_CLIENT,  
    unpack = function (msg, sz)  
        return host:dispatch(msg, sz)  
    end,  
    dispatch = function (_, _, type, ...)  
        if type == "REQUEST" then  
            local ok, result  = pcall(request, ...)  
            if ok then  
                if result then  
                    send_package(result)  
                end  
            else  
                skynet.error(result)  
            end  
        else  
            assert(type == "RESPONSE")  
            error "This example doesn't support request client"  
        end  
    end  
}  

  

協議的詳細部分看lualib/skynet.lua。

最后看看simpledb服務:

local skynet = require "skynet"  
require "skynet.manager"    -- import skynet.register  
local db = {}  
  
local command = {}  
  
function command.GET(key)  
    return db[key]  
end  
  
function command.SET(key, value)  
    local last = db[key]  
    db[key] = value  
    return last  
end  
  
skynet.start(function()  
    skynet.dispatch("lua", function(session, address, cmd, ...)  
        local f = command[string.upper(cmd)]  
        if f then  
            skynet.ret(skynet.pack(f(...)))  
        else  
            error(string.format("Unknown command %s", tostring(cmd)))  
        end  
    end)  
    skynet.register "SIMPLEDB"  
end)  

 

這里很簡單地處理了SET和GET。

 

以上只是大概瀏覽了一遍Skynet附帶的例子,了解了一些Skynet提供的lua接口,其他接口可以查看skynet.lua代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM