Delphi2010 the art network Abstract DataSnap

Delphi2010 the art network Abstract DataSnap

First, add a description for the DataSnap System Services

These days have been studying the Delphi DataSnap 2010, the sensation is really very powerful, and now enough reasons to prove that Delphi7 laid off.

DataSnap There are three service models, which established the way Windows Service Application service not described in the Description section is empty, the following methods can be used to add a service description:

Copy the code
procedure TServerContainer.ServiceAfterInstall(Sender: TService);
var
  reg: TRegistry;
begin
  reg := TRegistry.Create;
  try
    with reg do
    begin
      RootKey := HKEY_LOCAL_MACHINE;
      if OpenKey('SYSTEM/CurrentControlSet/Services/' + Self.Name, false) then
      begin
        WriteString('Description', '机房管理系统核心服务');
      end;
      CloseKey;
    end;
  finally
    reg.Free;
  end;
end;
 
Copy the code

 

Two, DataSnap server and client release distribution method

Server publishing method:

1. In the cell unit ServerMethodsUnit1 added uses MidasLib; (The purpose of adding MidasLib midas.dll release was omitted)

2. If you are using a Firebird database, simply copy dbxfb.dll and fbclient.dll, If you are using SQLite, you do not have to copy anything.

 Distributed server software only needs three files: your server program, dbxfb.dll and fbclient.dll

  

Client distribution method:

1. Plus uses MidasLib the client program; (purpose of adding MidasLib release was omitted Midas.dll)

2. If the server uses http protocol as DataSnap communication, then, need to add users DSHTTPLayer in the client program, if you use tcp agreement without this step.

Distribution of client software only one file: Your client program 

Server and the client does not need Midas.dll, do not need to register regsvr32 Midas.dll, datasnap seems Delphi2010 abandon the use of COM is really a lot of progress!

 

Three, DataSnap servers how to get the client's IP and port

As a server software, you must do the strong control of the client, you want to control, it is necessary to get basic information about the client's network, such as the client IP and port. With a client IP can be arbitrary manipulation of the client, such as termination of certain client connections, limiting function and so on.

 

How DataSnap server in Delphi2010 Get the client ip, really it took me some time, wondering why this feature is not the point of it more user-friendly, feature always conceal it. Programmers have to make like a treasure hunt to explore as a waste of time. I now put the finishing results dedicated to you, so you spend time in this study.

 

In addition, the study found, DSConnectEventObject.ChannelInfo.Id property is actually a memory address, is not a simple number. 

 

SUMMARY if .. then the following code which is critical. 

Copy the code
uses IdTCPConnection;

//...... 

procedure TServerContainer1.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
var
  ClientConnection: TIdTCPConnection;
begin
  with Form1 do
  begin
    dsShowDataSet.Append;
    dsShowDataSet['ClientConnectTime'] := Now;

    if DSConnectEventObject.ChannelInfo <> nil then
    begin
      ClientConnection := TIdTCPConnection(DSConnectEventObject.ChannelInfo.Id);

      dsShowDataSet['ClientID'] := DSConnectEventObject.ChannelInfo.Id;
      dsShowDataSet['ClientIP'] := ClientConnection.Socket.Binding.PeerIP +
        ':' + IntToStr(ClientConnection.Socket.Binding.PeerPort);
      dsShowDataSet['ServerIP'] := ClientConnection.Socket.Binding.IP + ':' +
        IntToStr(ClientConnection.Socket.Binding.Port);
    end;

    dsShowDataSet['ClientUserName'] := DSConnectEventObject.ConnectProperties
      [TDBXPropertyNames.UserName];
    dsShowDataSet['ClientUserPassword'] :=
      DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password];
    dsShowDataSet['ServerInfo'] := DSConnectEventObject.ConnectProperties
      [TDBXPropertyNames.ServerConnection];
    dsShowDataSet.Post;
  end;
end;
 
Copy the code

 

Alternatively, it can be:

Copy the code
procedure TServerContainer1.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
var
  ClientConnection: TDBXClientInfo;
  Val: TTCP_KeepAlive;
  Ret: DWord;
begin
  ClientConnection := DSConnectEventObject.ChannelInfo.ClientInfo;

  AddLog(
    ClientConnection.IpAddress
    +':'+
    ClientConnection.ClientPort
    +'登录服务器');

  UpdateLinkToList(ClientConnection.IpAddress
    +':'+
    ClientConnection.ClientPort
    ,IntToStr(DSConnectEventObject.ChannelInfo.Id)
    ,0);
end;
Copy the code

 

Four, DataSnap and the TCP keepAlive KeepAliveInterval (Heartbeat) Parameter Description

Delphi2010 in DataSnap, if the client abnormal dropped or unplug the network cable, then the server will leave a TCP connection, which will become a dead connection (tested, if the windows keep the TCP connection is disabled, then three hours damn connection not disappear). If a large number of concurrent client, TCP death appeared too many connections, server memory and ports will increase until the server's port filled and exhausted memory. If so, the server can not run a robust and stable. 

It can open another thread to monitor client connections, but today is not to give you on this method, but using the TCP protocol that comes with the package heartbeat function to solve this problem.

 

First look at the principles of TCP keep-alive 

A TCP keep-alive packet is a simple ACK, the ACK packet to a connected content than the current sequence number is smaller than a packet. Host receives these ACKs will return

A return containing the current sequence number of the ACK packet.
Keep-alives are generally used to authenticate the remote connection is valid. No other data is transmitted, or higher level of keep-alives is transmitted if the connection on, keep-alives are transmitted in each KeepAliveTime. (Default 7,200,000 milliseconds, which is two hours).

If the keep-alive response is not received, the retransmission keep-alive once every KeepAliveInterval seconds. KeepAliveInterval default is 1 second. NETBT Microsoft as part of the network functions used in many connections, more commonly transmitted NETBios keep-alives, therefore, usually is not transmitted in the TCP keep-alives NetBios connection.
TCP keep the connection is disabled by default, but Microsoft Sockets application can use SetSockOpt functions to enable them.


Consider the following class 

Copy the code
type 
  TCP_KEEPALIVE = Record 
    the OnOff: Cardinal; 
    the KeepAliveTime: Cardinal; // how long (ms) does not send the heartbeat packet data begins 
    KeepAliveInterval: Cardinal // how often (ms) send a heartbeat packet, sent five times (System value) 
End;
 
Copy the code

 

KeepAliveTime: TCP connection how long (in milliseconds) without a heartbeat packet data transmission begins, when the data transfer does not transmit heartbeat packets
KeepAliveInterval: how often (in milliseconds) to send a heartbeat packet sent five times (default value)

 

If the client network outages, server system after sending a heartbeat packet, the server will automatically lift the TCP connection. This, you can use the View command netstat -p -tcp

Next we will combine Delphi2010 DataSnap technology uses heartbeat package features! stay tuned

 

Fifth, the establishment of a stable heartbeat packets using TCP program of service

In order to make our service more stable program, some details must be resolved. As a speaking customers mentioned end unplug the network cable, resulting in a dead TCP connections on the server, if the number of dead too many connections, long-term stable operation of the server can be a huge threat.

 In addition, after testing, if there are dead TCP connections on the server, then connect to the database service program, that will produce a dead connection. In this case, also pose a threat to the database server. So, write server program will directly affect the stability of the system!

How to solve the problem of dead TCP connections, there are a number of ways, the most effective is the heartbeat packet technology.

 We join the heartbeat package code in the event DSServer in OnConnect

Copy the code
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;
Copy the code

 

Code above observation, we heartbeat packet onto the end of the service performed, if a TCP connection to the server is not received in 5 seconds of data, it will be sent to the peer sending the heartbeat packet interval of 3 seconds, 5 times continuously transmitted (see previous arguments detailed talk about advanced technology 4). If after five peer end does not answer, the server ends the TCP connection. TCP connections can use the netstat -p tcp command.

 

After the end of the TCP, written in delphi service program will automatically end and the connection to the database. I use the FireBird database, you can use the command to view

SELECT MON$USER, MON$REMOTE_ADDRESS,
  MON$REMOTE_PID,
  MON$TIMESTAMP
 FROM MON$ATTACHMENTS

 

Tcp connection now dead dead connections and database servers are cleared, our system will be able to long-term stable operation.


Sixth, strengthen the service routine control of visitors 

1) As a service program, if you do not limit the number of access clients, the consequences will be terrible. If someone spoof, servers overwhelmed, will run out of memory, the server will eventually downtime. How to limit the number of visitors it?

 

We can set a variable to record the number of visitors, if we exceed the established figures, then the subsequent connection request to the server, will be cut off.

 

2) limiting the number of access, but if you do not do password authentication, unrelated personnel will be able to login to the server! The solution is to pass the client user name and password, if a user name and password is incorrect, the connection will be disconnected.

The client's username and password properties SQLConnection1 in the Driver classification and set username and password.

 

3) Try not to set Maxthreads property DSTCPServerTransport1, as well as database connection pool is also not set, delphi2010 have a memory leak, these two parameters can be saved by default.

 

Add the following code OnConnect DSServer1 control event (using the tcp / ip connection):

 

Copy the code
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;
Copy the code

 

 Of course, after the addition of the manual version without the heartbeat packet code, it adds itself as TDSTCPServerTransport corresponding properties and functions, such as:

 

 

https://www.cnblogs.com/m0488/p/9759702.html

 

Guess you like

Origin www.cnblogs.com/railgunman/p/11456074.html