TServerSocket和TClientSocket做的C/S程序,如果ClientSocket端的计算机突然断电,当机,网线断开,TServerSocket如果才能快速的知道,反之,如果是TServerSocket端的计算机突然断电,当机,网线断开,TClientSocket如果才能快速的知道.
请高手帮忙.如有DEMO发给我[email protected]

解决方案 »

  1.   

    在ClientSocketDisconnect,ServerSocketClientDisconnect这个事件里判断
      

  2.   

    在ClientSocketDisconnect,ServerSocketClientDisconnect这个事件里判断在这两个事件里,断电的情况是不会触发这两个事件的.
      

  3.   

    或者看看能不能把tcp自己的timeout时间改短一点
      

  4.   

    能不能写点代码给我看下啊,都搞了好几个星期了,烦啊
    最好有DEMO
      

  5.   

    这两个控件很少用
    在服务器程序退出的情况下在ClientSocketDisconnect,ServerSocketClientDisconnect这个事件里可以判断,如果断电,网络断开可能用这个是判断不出来
    用TIdIcmpClient定时ping主机,断电,网络不通的话都可以检测出来
      

  6.   

    控件例子unit Main;interfaceuses
      {$IFDEF Linux}
      QGraphics, QControls, QForms, QDialogs, QStdCtrls, QExtCtrls,
      {$ELSE}
      windows, messages, graphics, controls, forms, dialogs, stdctrls, extctrls,
      {$ENDIF}
      SysUtils, Classes, IdIcmpClient, IdBaseComponent, IdComponent, IdRawBase, IdRawClient;
    type
      TfrmPing = class(TForm)
      lstReplies: TListBox;
      ICMP: TIdIcmpClient;
      Panel1: TPanel;
      btnPing: TButton;
      edtHost: TEdit;
      procedure btnPingClick(Sender: TObject);
      procedure ICMPReply(ASender: TComponent; const ReplyStatus: TReplyStatus);
      private
      public
      end;var
      frmPing: TfrmPing;implementation
    {$IFDEF MSWINDOWS}{$R *.dfm}{$ELSE}{$R *.xfm}{$ENDIF}procedure TfrmPing.btnPingClick(Sender: TObject);
    var
      i: integer;
    begin
      ICMP.OnReply := ICMPReply;
      ICMP.ReceiveTimeout := 1000;
      btnPing.Enabled := False; try
      ICMP.Host := edtHost.Text;
      for i := 1 to 4 do begin
      ICMP.Ping;
      Application.ProcessMessages;
      //Sleep(1000);
      end;
      finally btnPing.Enabled := True; end;
    end;procedure TfrmPing.ICMPReply(ASender: TComponent; const ReplyStatus: TReplyStatus);
    var
      sTime: string;
    begin
      // TODO: check for error on ping reply (ReplyStatus.MsgType?)
      if (ReplyStatus.MsRoundTripTime = 0) then
      sTime := '<1'
      else
      sTime := '=';  lstReplies.Items.Add(Format('%d bytes from %s: icmp_seq=%d ttl=%d time%s%d ms',
      [ReplyStatus.BytesReceived,
      ReplyStatus.FromIpAddress,
      ReplyStatus.SequenceId,
      ReplyStatus.TimeToLive,
      sTime,
      ReplyStatus.MsRoundTripTime]));
    end;end.
      

  7.   

    几次ping 不通的话就断开连接从新连,有个缺点,可能防火墙会设置禁止ping命令,ping不通其实网络是通的,这个要具体分析了,或者在协议里自己加心跳校验
      

  8.   

    打开TCP/IP的KeepAlive机制,把检测超时设短点,就可以自动检测。
      

  9.   

    solestar(孤星)通用做法是在协议里增加双向的心跳命令这样的方法怎么样实现啊?
      

  10.   

    用indy或者socket api吧,你这两个控件我不熟悉,没找到关于心跳方面的用法,IdSocket有心跳机制
    procedure SetSockOpt(level: Integer; optname: Integer; optval: PChar; optlen: Integer);Parameterslevel: IntegerOption level Id_SOL_SOCKET, Id_IPPROTO_TCP, or Id_IPPROTO_IP.
    optname: IntegerSocket option to receive the option value.
    optval: PCharValue for the requested option.
    optlen: IntegerLength of the option value buffer.
    例子我就不贴了
      

  11.   

    现在TClientSocket可以判断TServerSocket端是否在线了,用了个笨方法,
    但TServerSocket端还不可以判断TClientSocket端是否在线,请教中?
      

  12.   

    //使用keepalive
    unit utils_socketc;interface
    uses IdStackConsts,IdStackWindows,IdWinSock2;const
      IOC_IN               =$80000000;
      IOC_VENDOR           =$18000000;
      SIO_KEEPALIVE_VALS   =IOC_IN or IOC_VENDOR or 4;
    type tcp_keepalive=record
        onoff:Longword;
        keepalivetime:Longword;
        keepaliveinterval:Longword;
      end;
    //设置KeepAlive用于检测线路是否中断
    function SetKeepALive(const SockHandle:integer):Boolean;
    implementation
    uses typedefc,global_vspmc,showmsgc,inifilefuncv2;
    function SetKeepALive(const SockHandle:integer):Boolean;
    var
        KeepAliveIn   : tcp_keepalive;
        KeepAliveOut  : tcp_keepalive;
        Status        : Integer; 
        BytesReturned : Cardinal;
        enkeepalive:boolean;
        Akeepalivetime,Akeepaliveinterval:integer; 
    begin                              
    Result:=false;
    //是否启用KeepALive,默认为启用
    inifilefuncv2.readsect_boolean_ini(GVspmConfig_ini,
    cfg_globalcfg,cfg_enablekeepalive,enkeepalive,cfg_enablekeepalive_def);
    if not enkeepalive then exit;
    //默认发检测包间隔
    inifilefuncv2.readsect_integer_ini(GVspmConfig_ini,
    cfg_globalcfg,cfg_keepalivetime,Akeepalivetime,cfg_keepalivetime_def);inifilefuncv2.readsect_integer_ini(GVspmConfig_ini,
    cfg_globalcfg,cfg_keepaliveinterval,Akeepaliveinterval,cfg_keepaliveinterval_def);KeepAliveIn.onoff:=1;
    //发送检测包间隔
    KeepAliveIn.keepalivetime:=Akeepalivetime;
    //回应超时,默认情况下,如果出现超时,Windows将重新发送检测包,直到5次全部失败。
    KeepAliveIn.keepaliveinterval:=Akeepaliveinterval;
    Status:=WSAIoctl(SockHandle, SIO_KEEPALIVE_VALS,
                                   @KeepAliveIn,  SizeOf(KeepAliveIn),
                                   @KeepAliveOut, SizeOf(KeepAliveOut),
                                   @BytesReturned, nil, nil);
    if Status <> 0 then
       begin
         showmsgc.showNormal_msg('SetKeepAlive error','');
         exit;
       end;
     Result:=true;
    end;end.