delphi的程序,使用TServerSocket控件,如果拔掉网线的时候,无法捕捉到此时的网络断开事件(拔掉网线了),哪位知道如何解决?(50分)

R

rainfly

Unregistered / Unconfirmed
GUEST, unregistred user!
delphi的程序,使用TServerSocket控件,如果拔掉网线的时候,无法捕捉到此时的网络断开事件(拔掉网线了),哪位知道如何解决?
 
BTW,我使用阻塞方式,哪位DX有思路,还望不吝赐教,谢谢!
 
如果要捕捉网络断开事件,我想你可加一个时钟;
但这样可能很耗网络资源。不妨试一试!
 
如果网络断开应该可以返回socket错误信息,这是操作系统的责任
 
还是时钟比较简单,时刻查询用户是否在线,如果不在则通知用户,如果你觉得浪费系统
资源,你可以用诸如多线程之类的,不过多线程可能还是会比较费时,让我想想还有什么方法
 
捕获windows消息吧,我想应该有这个系统消息.up
 
服务器发信息,客户端听到后回信息,服务器一段时间听不到客户端的信息,就是吊线了!
 
服务器和客户端的连接断开时会产生错误的呀,处理SOCKET相关函数即可。
 
如果在已建立联接的情况下拔掉网线或把客户机突然断电(非正常中止SOCKET间的连接),
在发送数据时就会确发ONERROR事件,可在此事件中加入代码进行处理(根据返回的错误代
码可判断出是何种错误),处理完后再把ERRORCODE置为0,系统则不再提供有错误发生!!!
我曾经用过这种方法,不过感觉不是很好,有时会死机。建议使用UDP,该控件采用无连接
通讯方式,比TCP的使用方便得多。(个人意见,各位DFW有意见不要骂我,指点便是!)
 
在2000下100m的网卡,拔掉网线后系统有提示,而10m的则没有提示,
估计100m网卡在断网时会通知操作系统,至少会有个状态位供2000监测
 
没办法的,TCP没有检测连接是否断开的机制,如果打开哪个KEEPLIVE选项,也
只是没2个小时发包检测
 
=======>我使用阻塞方式
那就更简单,如果几分钟收不到新的数据包就断开连接~!
 
单独开个线程来检测,就像这样:
unit u_SocketChecker;

interface

uses
Classes, syncobjs, Windows, sysutils;

type
TSocketChecker = class(TThread)
private
{ Private declarations }
FCrit: TCriticalSection;
ThreadList: TList;
public
FShutDownEvent: TEvent;
public
constructor Create(CreateSuspend: Boolean);
destructor Destroy; override;
procedure Execute; override;
procedure AddThread(TT: TObject);
procedure RemoveThread(TT: TObject);
end;

implementation
uses u_ClientSocketThreadRoot, U_Logger;

{ TSocketChecker }

procedure TSocketChecker.AddThread(TT: TObject);
begin
FCrit.Enter;
ThreadList.Add(TT);
FCrit.Leave;
end;

constructor TSocketChecker.Create(CreateSuspend: Boolean);
begin
inherited Create(true);
FCrit := TCriticalSection.Create;
ThreadList := TList.Create;
FreeOnTerminate := true;
if not CreateSuspend then
resume;
end;

destructor TSocketChecker.Destroy;
begin
ThreadLIst.free;
ThreadLIst := nil;
FCrit.Free;
FCrit := nil;
inherited;
end;

procedure TSocketChecker.Execute;
var
TT: TClientSocketThreadRoot;
i: Integer;
CurrentTick: Integer;
TimeOutValue: Integer;
begin
{ Place thread code here }
while (not Terminated) and (FShutDownEvent.WaitFor(1000) = wrTimeout) do
begin
for i := 0 to ThreadList.Count - 1 do
begin
try
TT := TClientSocketThreadRoot(ThreadList.Items);
if TT.Socket.Connected then
begin
CurrentTick := GetTickCount;
try
TimeOutValue := StrToInt(TT.RunParams.Values['网络超时']);
except
TimeOutValue := 10000;
end;
if (CurrentTick - TT.FLastReadTimeStamp > TimeOutValue) or
(CurrentTick - TT.FLastWriteTimeStamp > TimeOutValue) then
begin
TT.Socket.Disconnect;
TT.FLastWriteTimeStamp := CurrentTick;
TT.FLastReadTimeStamp := CurrentTick;
LogIt('任务:<%s>网络超时,断开', [TT.RunParams.Values['任务名称']]);
end;
end;
except
break;
end;
end;
end;
end;

procedure TSocketChecker.RemoveThread(TT: TObject);
begin
FCrit.Enter;
ThreadList.Delete(ThreadList.IndexOf(TT));
FCrit.Leave;
end;

end.

 
truecat:您的方法是用在非阻塞方式下,而且在发送数据超时后才知道断链了,
响应太慢,不满足要求!
yinxuetao、xmodem:好像没有windows消息,2000下系统马上就能发现,不知MS怎么做的,谁知道?
无忌兄:如果建链后非正常断开(网线被拔),阻塞状态下的Server线程会检测到错误的,您说的没错!
但如果还没有建立任何连接而网线被拔掉呢?这时线程还没启动呢。

定时器的方法不可取,server不可预料会有哪个客户来连接,所以不能主动向客户发起连接。
 
u_ClientSocketThreadRoot, U_Logger是什么?
 
我用拨号上网,当我把电话线拨掉时,
使用 Err := WSAGetLastError();
程序会返回socket的错误10065,意思是找不到路由!
这个不知是不是你要的答案!
 
WinSock2有事件的。你打开SConnect.pas看看就明白了。我一直这样用,响应很好呀!
 
多人接受答案了。
 
顶部