Delphi2010中DataSnap高階技術(5)—建立穩定服務程式之TCP心跳包的使用
為了能讓我們的服務程式更加穩定,有些細節問題必須解決。就如上一講中提到的客戶端拔掉網線,造成伺服器上TCP變成死連線,如果死連線數量過多,對伺服器能長期穩定執行是一個巨大的威脅。
另外,經過測試,如果伺服器上有TCP死連線,那麼服務程式連線資料庫,也會產生那個一個死連線。這樣的話,給資料庫伺服器也造成威脅。所以,伺服器程式編寫的好壞,直接影響系統的穩定性!
如何解決TCP死連線的問題,有多種方法,其中最有效的就是心跳包技術。
我們在DSServer的OnConnect事件中加入心跳包程式碼
uses IdTCPConnection,IdWinsock2
........
type
TCP_KeepAlive = record
OnOff: Cardinal;
KeepAliveTime: Cardinal;
KeepAliveInterval: Cardinal;
end;
........
procedure TServerContainer1.DSServer1Connect
(DSConnectEventObject: TDSConnectEventObject);
var
Val: TCP_KeepAlive;
Ret: DWord;
ClientConnection: TIdTCPConnection;
begin
ClientConnection := TIdTCPConnection(DSConnectEventObject.ChannelInfo.Id);
Val.OnOff := 1;
Val.KeepAliveTime := 5000;
Val.KeepAliveInterval := 3000;
WSAIoctl(ClientConnection.Socket.Binding.Handle, IOC_IN or IOC_VENDOR or 4,
@Val, SizeOf(Val), nil, 0, @Ret, nil, nil);
end;
觀察上述程式碼,我們把心跳包放到服務端上執行,如果伺服器的某個TCP連線在5秒鐘沒有收到資料,將會發送向對端傳送心跳包,間隔3秒鐘,連續傳送5次(引數詳解見上一講高階技術4)。如果5次以後對端還沒有應答,伺服器將結束該TCP連線。TCP的連線可以使用 netstat -p tcp 命令檢視。
當該TCP結束後,delphi編寫的服務程式會自動結束和資料庫的連線。我用的是FireBird資料庫,大家可以使用命令檢視 SELECT MON$USER, MON$REMOTE_ADDRESS,
MON$REMOTE_PID,
MON$TIMESTAMP
FROM MON$ATTACHMENTS
現在伺服器的tcp死連線和資料庫的死連線都清除了,我們的系統將能長期穩定的執行。