zoukankan      html  css  js  c++  java
  • tcp心跳机制

    對連接上來的連接,進行檢測,以防止客戶端異常關閉,或線路異常斷開,而服務器不知道,得到一個半連接這種情況。

    當然可以在協議裡加一個心跳包,然後服務器端定時檢測,過一段時間就去輪訓一次,看哪些連接超過多少時間沒有反應。超時就關閉。但這樣有點不爽,要自己寫代碼來完成。還要鎖定連接列表,代價挺大的。

    記得以前在網上看到可以用 TCP 的 KeepAlive 保活機制來做,但也看到人說沒有效果。我想定TCP協議的那此人,不會定一些無用的功能吧,但MSDN上卻沒看到什麼有價值的東東。難道MS沒有實現它們?我決定試試。

    1. Delphi 的 WinSock2.pas 不全,要加入一些東東,如下:

    const
    IOC_IN               =80000000 H; // 這裡是 80000000 十六進制,Blog 有問題
    IOC_VENDOR           =18000000 H; // 這裡是 80000000 十六進制,Blog 有問題
    IOC_out              =40000000 H; // 這裡是 80000000 十六進制,Blog 有問題
    SIO_KEEPALIVE_VALS   =IOC_IN or IOC_VENDOR or 4;

    type
    TTCP_KEEPALIVE = packed record
        onoff             : integer;
        keepalivetime     : integer;
        keepaliveinterval : integer;
    end;


    2. 在 accept 得到新連接時,設定它的保活時間, 如下:

        // Set KeepAlive 開啟保活機制
        opt := 1;
        if setsockopt(hClient,SOL_SOCKET, SO_KEEPALIVE, @opt, SizeOf(opt)) <> 0 then
        begin
          OutputDebugString('setsockopt KeepAlive Error!!!');
        end;

        // KeepAlive Time 設保活時間
        klive.onoff := 1;              // 啟用保話
        klive.keepalivetime := 10000; // 保話超時
        klive.keepaliveinterval := 1; // 超時次數
        if WSAIoctl( hClient, SIO_KEEPALIVE_VALS,
                     @klive,
                     SizeOf(TTCP_KEEPALIVE),
                     @outKlive,
                     SizeOf(TTCP_KEEPALIVE),
                     @opt,
                     0,nil) = SOCKET_ERROR then
        begin
          OutputDebugString('WSAIoctl KeepAlive Error');
        end;

    =======================================================

    有开发网络应用经历的人都知道,网络中的接收和发送数据都是使用WINDOWS中的SOCKET进行实现。但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。可是如何判断这个套接字是否还可以使用呢?

      有人一定想到使用Send函数中的返回结果来进行判断。如果返回的长度和自己发送出去的长度一致,那就说明这个套接字是可用的,否则此套接字一定出现了问题。但是我们并不是无时无刻的发送数据呀。如何解决呢?

      其实TCP中已经为我们实现了一个叫做心跳的机制。如果你设置了心跳,那TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),并且此信息不会影响你自己定义的协议。

      在VC中实现心跳的例子很多,可是在DLEPHI中一直没有相应的代码。下面我是我使用DELPHI编写的关于心跳的代码(以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;

    实现代码是在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;
    //设置3秒钟时间间隔

      inKeepAlive.keepalivetime:=3000;

    //设置每3秒中发送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;

    如果加入以上的代码以后,系统会每3秒中加入一次的心跳。并且如果客户端断线以后(网线断),函数GetQueuedCompletionStatus会返回FALSE。

    if (GetQueuedCompletionStatus(CompletionPort, BytesTransferred,DWORD(PerHandleData), POverlapped(PerIoData), INFINITE) = False) then
    begin
    //在这里处理客户端断线信息。

       continue;
    end;

    以上就是我使用心跳的方法,此方法我已经在我的网络游戏中使用。情况稳定!

  • 相关阅读:
    weka使用笔记1cluster内方法的使用
    RCP导出的错误解决
    hadoop 无法启动tasktrack 和jobtrack 解决办法
    前段技术
    数字信号处理 - chap1 采样
    数字信号处理 - chap5 数字信号频谱
    数字信号处理-chap3 滤波、差分方程、卷积
    数字信号处理 - Chap7 DFT和FFT (1)DFT基础
    数字信号处理 - chap2 数字信号
    数字信号处理 - Chap8 小波 (1)基础
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2940920.html
Copyright © 2011-2022 走看看