------轉自 http://apps.hi.baidu.com/share/detail/33014978
有開發網絡應用經歷的人都知道,網絡中的接收和發送數據都是使用WINDOWS中的SOCKET進行實現。但是如果此套接字已經斷開,那發送數據和接收數據的時候就一定會有問題。可是如何判斷這個套接字是否還可以使用呢?
有人一定想到使用Send函數中的返回結果來進行判斷。如果返回的長度和自己發送出去的長度一致,那就說明這個套接字是可用的,否則此套接字一定出現了問題。但是我們並不是無時無刻的發送數據呀。如何解決呢?
其實TCP中已經為我們實現了一個叫做心跳的機制。如果你設置了心跳,那TCP就會在一定的時間(比如你設置的是3秒鍾)內發送你設置的次數的心跳(比如說2次),並且此信息不會影響你自己定義的協議。
在VC中實現心跳的例子很多,可是在DELPHI中一直沒有相應的代碼。下面我是我使用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;