• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            專職C++

            不能停止的腳步

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              163 Posts :: 7 Stories :: 135 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(28)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/jimaliu/archive/2009/11/30/4908658.aspx


            用戶異常掉線檢測
                                             David.Zhu  2005/6/1
               目前主要有三種方法來實現(xiàn)用戶掉線檢測:SO_KEEPALIVE ,SIO_KEEPALIVE_VALS 和Heart-Beat線程。
            下面我就上面的三種方法來做一下介紹。
            (1)SO_KEEPALIVE 機制
                    這是socket庫提供的功能,設(shè)置接口是setsockopt API:
               BOOL  bSet=TRUE;
               setsockopt(hSocket,SOL_SOCKET,SO_KEEPALIVE,(const char*)&bSet,sizeof(BOOL));

                   根據(jù)MSDN的文檔,如果為socket設(shè)置了KEEPALIVE選項,TCP/IP棧在檢測到對方掉線后,
               任何在該socket上進行的調(diào)用(發(fā)送/接受調(diào)用)就會立刻返回,錯誤號是WSAENETRESET ;
               同時,此后的任何在該socket句柄的調(diào)用會立刻失敗,并返回WSAENOTCONN錯誤。

               該機制的缺點也很明顯:
                     默認設(shè)置是空閑2小時才發(fā)送一個“保持存活探測分節(jié)”,不能保證實時檢測!
               當然也可以修改時間間隔參數(shù),但是會影響到所有打開此選項的套接口!
                     關(guān)聯(lián)了完成端口的socket可能會忽略掉該套接字選項。


            (2)SIO_KEEPALIVE_VALS 機制
                     這是從彭博兄那里學(xué)到一個機制拉,設(shè)置接口是WSAIoctl API:
                 DWORD dwError = 0L ;
                 tcp_keepalive sKA_Settings = {0}, sReturned = {0} ;
                 sKA_Settings.onoff = 1 ;
                 sKA_Settings.keepalivetime = 5500 ; // Keep Alive in 5.5 sec.
                 sKA_Settings.keepaliveinterval = 3000 ; // Resend if No-Reply
                 if (WSAIoctl(skNewConnection, SIO_KEEPALIVE_VALS, &sKA_Settings,
                      sizeof(sKA_Settings), &sReturned, sizeof(sReturned), &dwBytes,
                      NULL, NULL) != 0)
                 {
                       dwError = WSAGetLastError() ;
                 }
                 實現(xiàn)時需要添加tcp_keepalive and SIO_KEEPALIVE_VALS的定義文件MSTCPiP.h
                 該選項不同于SO_KEEPALIVE 機制的就是它是針對單個連接的,對系統(tǒng)其他的套接
                 口并不影響。
                    針對完成端口的socket,設(shè)置了SIO_KEEPALIVE_VALS后,激活包由TCP STACK來負責。
                 當網(wǎng)絡(luò)連接斷開后,TCP STACK并不主動告訴上層的應(yīng)用程序,但是當下一次RECV或者SEND操作
                 進行后,馬上就會返回錯誤告訴上層這個連接已經(jīng)斷開了.如果檢測到斷開的時候,在這個連接
                 上有正在PENDING的IO操作,則馬上會失敗返回.


                 該機制的缺點:
                         不通用啦。MS的API只能用于Windows拉。不過,呵呵用彭博兄的評論就是:
                 優(yōu)雅一些^_^.
               
            (3)Heart-Beat線程
                    沒說的。自己寫一個后臺線程,實現(xiàn)Heart-Beat包,客戶端受到該包后,立刻返回相應(yīng)的反饋  包。

                該方法的好處是通用,但缺點就是會改變現(xiàn)有的通訊協(xié)議!

            有開發(fā)網(wǎng)絡(luò)應(yīng)用經(jīng)歷的人都知道,網(wǎng)絡(luò)中的接收和發(fā)送數(shù)據(jù)都是使用WINDOWS中的SOCKET進行實現(xiàn)。但是如果此套接字已經(jīng)斷開,那發(fā)送數(shù)據(jù)和接收數(shù)據(jù)的時候就一定會有問題。可是如何判斷這個套接字是否還可以使用呢?

              有人一定想到使用Send函數(shù)中的返回結(jié)果來進行判斷。如果返回的長度和自己發(fā)送出去的長度一致,那就說明這個套接字是可用的,否則此套接字一定出現(xiàn)了問題。但是我們并不是無時無刻的發(fā)送數(shù)據(jù)呀。如何解決呢?

              其實TCP中已經(jīng)為我們實現(xiàn)了一個叫做心跳的機制。如果你設(shè)置了心跳,那TCP就會在一定的時間(比如你設(shè)置的是3秒鐘)內(nèi)發(fā)送你設(shè)置的次數(shù)的心跳(比如說2次),并且此信息不會影響你自己定義的協(xié)議。

              在VC中實現(xiàn)心跳的例子很多,可是在DLEPHI中一直沒有相應(yīng)的代碼。下面我是我使用DELPHI編寫的關(guān)于心跳的代碼(以IOCP為例),希望對大家有幫助。

            定義心跳常量

            const
              IOC_IN               =$80000000;
              IOC_VENDOR           =$18000000;
              IOC_out              =$40000000;
              SIO_KEEPALIVE_VALS   =IOC_IN or IOC_VENDOR or 4;

            var

              inKeepAlive,OutKeepAlive:TTCP_KEEPALIVE;

            實現(xiàn)代碼是在Acceptsc:= WSAAccept(Listensc, nil, nil, nil, 0);代碼的后面加入:

                  opt:=1;
                  if setsockopt(Acceptsc,SOL_SOCKET,SO_KEEPALIVE,@opt,sizeof(opt))=SOCKET_ERROR then
                  begin
                    closesocket(Acceptsc);
                  end;
                  inKeepAlive.onoff:=1;
                  //設(shè)置3秒鐘時間間隔

              inKeepAlive.keepalivetime:=3000;

                  //設(shè)置每3秒中發(fā)送1次的心跳
                  inKeepAlive.keepaliveinterval:=1;
                  insize:=sizeof(TTCP_KEEPALIVE);
                  outsize:=sizeof(TTCP_KEEPALIVE);
                  if WSAIoctl(Accept,SIO_KEEPALIVE_VALS,@inKeepAlive,insize,@outKeepAlive,outsize,@outByte,nil,nil)=SOCKET_ERROR then
                  begin
                    closesocket(Acceptsc);
                  end;

            如果加入以上的代碼以后,系統(tǒng)會每3秒中加入一次的心跳。并且如果客戶端斷線以后(網(wǎng)線斷),函數(shù)GetQueuedCompletionStatus會返回FALSE。

            if (GetQueuedCompletionStatus(CompletionPort, BytesTransferred,DWORD(PerHandleData), POverlapped(PerIoData), INFINITE) = False) then
                    begin
                       //在這里處理客戶端斷線信息。

               continue;
                    end;

            以上就是我使用心跳的方法,此方法我已經(jīng)在我的網(wǎng)絡(luò)游戲中使用。情況穩(wěn)定!

             

            本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/jimaliu/archive/2009/11/30/4908658.aspx

            posted on 2010-11-25 17:09 冬瓜 閱讀(1172) 評論(0)  編輯 收藏 引用 所屬分類: 轉(zhuǎn)貼
            亚洲国产精品人久久| 99久久精品国产麻豆| 久久人人超碰精品CAOPOREN| 亚洲国产成人久久一区久久| 人妻无码αv中文字幕久久| 亚洲一区中文字幕久久| 亚洲国产小视频精品久久久三级 | 狠狠色狠狠色综合久久| 大香网伊人久久综合网2020| 青青草原综合久久大伊人| 久久线看观看精品香蕉国产| 伊人久久大香线蕉av不卡| 久久婷婷激情综合色综合俺也去| 精品一久久香蕉国产线看播放 | 久久精品国产一区二区三区日韩| 久久精品国产亚洲av麻豆图片| 国产精品VIDEOSSEX久久发布| 亚洲国产精品无码久久久久久曰| 久久精品天天中文字幕人妻| 久久水蜜桃亚洲av无码精品麻豆| 人人狠狠综合久久亚洲88| 伊人久久综合精品无码AV专区| 久久久久亚洲AV无码专区网站| 久久国产热精品波多野结衣AV| 无码人妻久久一区二区三区蜜桃 | 精品少妇人妻av无码久久| 亚洲第一极品精品无码久久| 久久人人添人人爽添人人片牛牛 | 久久亚洲私人国产精品| 亚洲国产成人久久综合区| 久久久久久国产a免费观看不卡| 狠狠久久综合| 亚洲午夜久久影院| 91久久精品视频| 久久99精品久久久久久野外| 久久亚洲国产中v天仙www| 久久99精品国产一区二区三区 | 久久久久久精品免费免费自慰| 久久99久久成人免费播放| 久久久久99精品成人片牛牛影视| 国产成人精品久久亚洲|