想请 富豪 张无忌 大侠 帮忙回答一个问题!(100分)

  • 主题发起人 主题发起人 eMetal
  • 开始时间 开始时间
E

eMetal

Unregistered / Unconfirmed
GUEST, unregistred user!
在TServerClientThread 编程中,已经建立了连接,但对方突然非正常关机了,该怎么办?
 
最好是定义一个实时检查的机制,如果定时发送一个特定的字符到client,client接收到后
会一个应答。这样如果长时间没有交互的话,就认为socket连接已经中断了。
如果没有这样的机制,好像最短也要2个小时才能知道对方已经断开了。
 
每次发送后, 用select函数判断超时情况, 下面这个可是在我的项目中久经考验的一个函数了:

int RecvTimeOut(int fd, unsigned int sec)
{
fd_set fs;
struct timeval timeout;
int n;

FD_ZERO(&fs);
FD_SET((unsigned int)fd,&fs);
timeout.tv_sec = sec;
timeout.tv_usec = 0;
n=select(fd+1,&fs,NULL,NULL,&timeout);
return n;
}

例:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ClientSocket1->Socket->SendBuf(100, sizeof(int));
//如果60秒还没有回应, 就判断超时(或认为网络中断也行), 关闭连接
if (RecvTimeOut(ClientSocket1->Socket->Handle, 60))
ClientSocket1->Close();
}
 
帮你翻译成Delphi代码了(我还没调试过),试试看吧:
function RecvTimeOut(sockfd: Integer; sec: Integer): Integer;
var
fs: TFDSet;
timeout: timeval;
n: Integer;
begin
FD_ZERO(fs);
FD_SET(sockfd, fs);
timeout.tv_sec := sec;
timeout.tv_usec := 0;
n := select(sockfd+1, @fs, nil, nil, @timeout);
Result := n;
end;
 
TServerSocketThread有个很还用的函数WaitForData(TimeOut)可以设置超时
 
to 张无忌:
在我的程序中已经有有用到WaitForData了

具体如:
while (not Terminated) and ClientSocket.Connected do
begin
Stream := TWinSocketStream.Create(ClientSocket, 60000);
try
if (Stream.WaitForData(60000)) then
begin

count:=Stream.Read(buffer, nNeed );
...

end
finally
stream.free;
end
end
 
提示无法连接
返回
 
真的没有人 能解决这个问题吗?
 
上面不是说得很清楚了吗,正常情况下,如果socket断开了,是可读可写的(就是select时
有返回成功),但读写返回都是0。非正常的中断,tcp/ip协议是不知道的,除非等超时
了,但这个超时是2个小时,并且是在你设置了检查机制后才有的(就是用setsocketopt())
为了避免这种情况,最后就是定时发送交互信息,如果超时发送或者接收,就认为socket断开。
 
WaitForData(TimeOut)返回的时候检查一下,如果没有收到任何数据就可以判断对方异常断开
 
接受答案了.
 
后退
顶部