Delphi2010中DataSnap高階技術(6)—加強服務程式對訪問者的控制能力
1)作為一個服務程式,如果不限制客戶端訪問數量,後果將是很可怕的。如果有人惡搞,伺服器不堪重負,記憶體將耗盡,最終伺服器將宕機。如何限制訪問者的數量呢?
我們可以設定一個變數,來記錄來訪者的數量,如果超過我們既定的數字,那麼後續的連線伺服器請求,都將被斷掉。
2)限制了訪問數量,但是如果不做密碼身份認證,無關的人員也將能登陸伺服器!解決辦法是客戶端傳入使用者名稱和密碼,如果使用者名稱和密碼不正確,連線將被結束通話。
在客戶端的SQLConnection1中driver分類的username和password屬性設定好使用者名稱和密碼。
3)儘量不要設定DSTCPServerTransport1的Maxthreads屬性,還有資料庫連線池也不要設定,delphi2010會有記憶體洩露,這兩個引數儲存預設即可。
在dsserver1控制元件的onconnect事件中加入如下程式碼(使用的是tcp/ip連線):
procedure TMainForm.DSServer1Connect
(DSConnectEventObject: TDSConnectEventObject);
var
val: TCP_KeepAlive;
Ret: Integer;
ClientConnection: TIdTCPConnection;
begin
// 最大連線數量,驗證來訪者密碼
if (DSConnectEventObject.ChannelInfo = nil) or (Connections >= 500) or
(DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName]
<> 'sunstone') or (DSConnectEventObject.ConnectProperties
[TDBXPropertyNames.Password] <> 'mypassword') then
begin
DSConnectEventObject.DbxConnection.Destroy;
// ClientConnection.Disconnect;
end
else
begin
// 獲取socket連線
ClientConnection := TIdTCPConnection(DSConnectEventObject.ChannelInfo.Id);
ClientConnection.OnDisconnected := ClientDisconnectEvent;
// 記錄來訪者數量
inc(Connections);
lblShowConnections.Caption := IntToStr(Connections);
if Trim(ShowConnections.Cells[0, 1]) <> '' then
ShowConnections.RowCount := ShowConnections.RowCount + 1;
ShowConnections.Cells[0, ShowConnections.RowCount - 1] := IntToStr
(DSConnectEventObject.ChannelInfo.Id);
ShowConnections.Cells[1, ShowConnections.RowCount - 1] :=
ClientConnection.Socket.Binding.PeerIP + ':' + IntToStr
(ClientConnection.Socket.Binding.PeerPort);
ShowConnections.Cells[2, ShowConnections.RowCount - 1] :=
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName];
ShowConnections.Cells[3, ShowConnections.RowCount - 1] :=
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password];
ShowConnections.Cells[4, ShowConnections.RowCount - 1] := FormatDateTime
('yyyy-mm-dd hh:nn:ss', Now);
// ShowConnections.Cells[6, ShowConnections.RowCount - 1] :=
// DSConnectEventObject.ConnectProperties
// [TDBXPropertyNames.ServerConnection];
// 設定心跳包
val.OnOff := 1;
val.KeepAliveTime := 5000;
val.KeepAliveInterval := 1000;
WSAIoctl(ClientConnection.Socket.Binding.Handle, IOC_IN or IOC_VENDOR or 4,
@val, SizeOf(val), nil, 0, @Ret, nil, nil);
end;
end;