应该是一个老问题吧,大家帮帮忙:就是如何及时有效的检测TCP无效链接?(50分)

  • 主题发起人 主题发起人 陌生
  • 开始时间 开始时间

陌生

Unregistered / Unconfirmed
GUEST, unregistred user!
由于对于WinSock、Tcp/Ip不是十分了解,最近有个问题一直没有办法可以有效地解决,就是在上位机(PC机)和下位机(CDMA模块)通讯的时候非常容易会产生一些无效的TCP链接,在下位机已经断开链接的时候上位机还是会保持其连接信息。在论坛大致的搜索了一下,也没有找到很好的答案,我现在使用的是Indy组件,不知道大家有什么好的办法没有,给推荐以下。在线:fjw8205@hotmail.com
 
to maze:谢谢,这种方法是可以解决这样的问题,但是有可能会不太及时,当然心跳频率可以适当的提高,但又牵涉到通信费用的问题(因为是CDMA的通讯)。我现在在想是不是在WinSocket通讯的设置里面会有这样的参数可以设定,然后在连接失效的时候可以马上发现。
 
贴点代码给你,看能不能帮助你
unit Link;


interface


function GateWay:string;
procedure IfLink;

implementation

uses

main,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,Registry,
Grids;


function GateWay:string;
var
Reg :TRegistry;
MyStr : TStrings;
buffer : array[0..1024] of byte;
i:integer;
info:TRegKeyInfo ;
str:string;
begin
Result:='0';
Reg :=TRegistry.Create;
Mystr:=Tstringlist.Create;
try
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if Reg.OpenKey('SOFTWARE/Microsoft/Windows NT/CurrentVersion/NetworkCards',false) then
begin
if reg.GetKeyInfo(info) then
begin

reg.GetKeyNames(mystr);
str:='SOFTWARE/Microsoft/Windows NT/CurrentVersion/NetworkCards/'+Mystr.Strings[0];
end;
end;
finally
Reg.CloseKey;
Mystr.Free;
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if reg.OpenKey(str,false) then
begin
str:=reg.ReadString('ServiceName');
end;
Reg.CloseKey;
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if reg.OpenKey('SYSTEM/CurrentControlSet/Services/'+str+'/Parameters/Tcpip/',false) then
begin
str:='';
for i:= 1 to reg.ReadBinaryData('defaultGateway',buffer,sizeof(buffer)) do
str:=str+chr(dword(buffer[i-1]));
end;
if str=chr(0) then
begin
str:='';
for i:= 1 to reg.ReadBinaryData('DhcpDefaultGateway',buffer,sizeof(buffer)) do
str:=str+chr(dword(buffer[i-1]));
end;

Reg.CloseKey;
reg.Free;
if (str=char(0)) or (str='') then
str:='66.218.71.88';
result:=str;
end;
end;
procedure IfLink;

begin
with mainForm do begin

ICMP.ReceiveTimeout:=10;
try
ICMP.Host := GateWay;


ICMP.Ping;

linklabel.caption:='正常';
linkLabel.Font.Color:=clGreen;
except
linklabel.caption:='断开';
mainform.linkLabel.Font.Color:=clred;
end;
end;
end;

end.
 
//设置保留连接超时
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3438148

function TCustomSocket.SetSocketKeepAlive(const S: TSocket = INVALID_SOCKET; const Value: Integer = 60000): Boolean;
type
TCP_KeepAlive = record
OnOff: Cardinal;
KeepAliveTime: Cardinal;
KeepAliveInterval: Cardinal
end;
var
Val: TCP_KeepAlive;
Ret: DWord;
Sock: TSocket;
begin
if Sock <> INVALID_SOCKET then
Sock := S
else Sock := SocketHandle;
Val.OnOff:=1;
Val.KeepAliveTime:= Value; // Defaule 60000 6秒
Val.KeepAliveInterval:= 500;
Result := SOCKET_ERROR <> WSAIoctl(Sock, IOC_IN or IOC_VENDOR or 4,
@Val, SizeOf(Val), nil, 0, @Ret, nil, nil)
end;

//要不用个线程来检查是否为活动连接,最保险。
 
呵呵,也可能是INDY组件的问题,自己看看代码吧。 不过这个检测机制还是要有的。
 
呵呵,没有办法,如果是物理层出现的问题,TCP连接不一定能够及时检测到,TCP协议本身也有心跳检测机制,但是根据我的经验,如果一个TCP连接两到三个小时没有任何动作,那么往往就成为一个无效连接了,但是这个连接的两端程序并不会收到任何通知。
所以使用TCP的通信,一定要加心跳检测,只需要一个字节的心跳包都OK了。
 
后退
顶部