1. 程式人生 > >Delphi2010中DataSnap高階技術(6)—加強服務程式對訪問者的控制能力

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;