遊戲服務器心跳包的作用

轉自:點擊打開鏈接

首先查一下tcp的斷線是否真的可靠

看到了一位同學的經驗

點擊跳轉到原文

         之前的測試都是,手動強制關閉客戶端進程,然後查看服務器的情況,結果往往是,服務器收到了客戶端關閉的事件。其實,我一直忽略了一個問題,我沒有拔掉網線來測試!

        上面的手動關閉客戶端進程,事實上並不能測試出想要的結果,因爲進程是在應用層的,所以,這種測試方法不能保證網絡驅動層也不發送數據報文給服務器。經過測試發現,當應用層強制結束進程時,對於TCP連接,驅動層會發送reset數據包!而服務器收到這個數據包就可以正常關閉了!

        那麼,如果拔掉網線呢,服務器收不到這個數據包,就會導致死連接存在!

        所以,心跳包是必要的,或者應用TCP協議本身的Keep-alive來設置

        之所以產生前面的誤解,也是由於以前看書的時候,憑空想象,以爲TCP連接如同一條繩子,一方斷開了,另外一方必然會知道的。殊不知,TCP連接,這個“面向連接”的連接並不存在,它只是抽象出來的概念,對於物理層,對於網線、光纖而言,不存在連接不連接的概念,因爲,對它們而言,無非就是一些電流脈衝而已。TCP的連接,不過是通過ACK、SEQ這些機制來模擬實現的。

以上爲引用

這麼看來socket本身的斷開通知不是很靠譜,心跳包會更合理一些

那麼心跳包的一個意義就是可以更可靠的檢測連接是否暢通


之後詢問了一下組內其他同學

他們表示,頁遊之前會用心跳包檢測加速作弊

比如如果某玩家應用加速器作弊,那麼他發送的心跳包時間時間間隔就會異常,這樣就可以揪出作弊,但是。。作弊器已經越來越高端了,檢測心跳包已經幾乎沒用,所以這個作用幾乎沒有了

心跳包曾經可以檢測作弊


組內同學還表示,心跳包可以檢測遊戲延遲,不過。。。手遊我檢測個什麼延遲

心跳包可以檢測遊戲延遲



skynet-mmo中心跳相關代碼

local last_heartbeat_time
local HEARTBEAT_TIME_MAX = 3 * 100 -- 3秒鐘未收到消息,則判斷爲客戶端失聯
local function heartbeat_check ()
if HEARTBEAT_TIME_MAX <= 0 or not user_fd then return end

local t = last_heartbeat_time + HEARTBEAT_TIME_MAX - skynet.now ()
if t <= 0 then
syslog.debugf ("--- heatbeat:%d, last:%d, now:%d", HEARTBEAT_TIME_MAX, last_heartbeat_timem, skynet.now() )

syslog.warning ("--- heatbeat check failed, exe kick_self()")
kick_self ()
else
skynet.timeout (t, heartbeat_check)
end
end


然後在每次收到客戶端消息時,更新一下last time

local function handle_request (name, args, response)
local f = REQUEST[name]
if f then
syslog.debug ("^^^@ request from client, exe func:%s", name)
local ok, ret = xpcall (f, traceback, args)
if not ok then
syslog.warningf ("handle message(%s) failed : %s", name, ret)
kick_self ()
else
last_heartbeat_time = skynet.now () -- 每次收到客戶端端請求,重新計時心跳時間
if response and ret then -- 如果該請求要求返回,則返回結果
send_msg (user_fd, response (ret))
end
end
else
syslog.warningf ("----- unhandled message : %s", name)
kick_self ()
end
end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章