Delphi2010 Datasnap Advanced Technology Date: December 1, 2010 Sunstone Original popularity: 13498 views: [Font size in large font] (1)-Add a description for the DATASNAP system service Program
These days have been studying the Delphi 2010 Datasnap, feel the function is really very powerful, now sufficient reason to prove that Delphi7 should be laid off.
DATASNAP has three service modes, in which the service Application mode is not described, the description is empty, and the feeling is always missing something.
Now find a way to add a description:
Procedure Tservercontainer2.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 ', ' It is my service ');
End
Closekey;
End
Finally
Reg. Free;
End
End
(2)-datasnap Server and client publishing and distribution method
Continue to study Datasnap technology these days.
For server and client software, how to publish it? After research, the distribution method is very simple!
Server Publishing Method:
1. In unit ServerMethodsUnit1, add uses midaslib; (the purpose of adding midaslib is to save the release Midas.dll)
2. I'm using a fire bird database, just copy Dbxfb.dll and Fbclient.dll
Distributed server Software requires only three files: Your server programs, Dbxfb.dll, and Fbclient.dll
Client Publishing Method:
1. Add uses Midaslib to the client program (the purpose of adding midaslib is to save the release Midas.dll)
2. If the server uses the HTTP protocol as DATASNAP communication, you also need to add the users Dshttplayer in the client program, if you use the TCP protocol, you do not need this step
The client software that is distributed requires only one file: your client program
The server and the client need not Midas.dll, also do not need to register regsvr32 Midas.dll, it seems Delphi2010 datasnap abandon use com really progress many!
The release program is so simple!!!
(3) How the-DATASNAP server gets the IP and port of the client
As a server software, must do a strong control of the client, want to control, you must get the client's network basic information, such as client IP and port. With the client IP, you can manipulate the client as you like, such as terminating some client connections, restricting functionality, and so on.
Datasnap server in delphi2010 How to get the client IP, it took me a bit of time, it is strange why this function does not do a more humane point, the function is always tucked away. It's time for programmers to fumble like treasure hunts. Now I dedicate the results to everyone so that we don't have to spend time studying this.
In addition, the study found that the DSConnectEventObject.ChannelInfo.Id property is actually a memory address, not a simple number.
The red part of the following code is key.
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
(4)-tcp keepalive and KeepAliveInterval parameters
Delphi2010 in Datasnap, if the client abnormally dropped or unplug the network cable, then the server will leave a TCP connection, the connection will become a dead connection (after testing, if the TCP to keep the connection of Windows disabled, three hours the connection does not disappear). If a large number of clients are concurrent and there are too many dead TCP connections, the server memory and port will increase until the server is full of ports and memory is exhausted. If so, the server does not run robustly and stably.
You can use another thread to monitor the client connection, but this is not the method to be explained today, but instead uses the TCP protocol's own heartbeat packet function to solve the problem.
Let's start by understanding the TCP keep-alive principle
A TCP keep-alive packet is a simple ACK that contains a packet that is less than the current connection sequence number one. The host receives these acks will return
Returns an ACK packet containing the current sequence number. Keep-alives is generally used to verify that the remote connection is valid. If no other data on the connection is transmitted, or the keep-alives of the higher level is transmitted, keep-alives is sent at each keepalivetime. (the default is 7,200,000 milliseconds, which is 2 hours).
If you do not receive a keep-alive response, Keep-alive will be re-sent every keepaliveinterval seconds. KeepAliveInterval default is 1 seconds. As with NETBT connections in many parts of Microsoft network features, it is more common to send NetBIOS keep-alives, so TCP keep-alives are not normally sent in NetBIOS connections. TCP hold connections are disabled by default, but Microsoft Sockets applications can use the SetSockOpt function to enable them.
Take a look at the following classes
Type tcp_keepalive = Record onoff:cardinal; keepalivetime:cardinal; How long (MS) does not have data to start send heartbeat packet keepaliveinterval:cardinal//How often (MS) send a heartbeat packet, Hair 5 times (System value) end;
KEEPALIVETIME:TCP connection how long (milliseconds) no data to start sending heartbeat packets, there is data delivery when the heartbeat packet is not sent KeepAliveInterval: How often (in milliseconds) to send a heartbeat packet, sent 5 times (system default)
If the client network is interrupted, the server automatically unlocks the TCP connection after the server system sends a heartbeat packet. This, you can use the Netstat-p-tcp command to view
Next we'll combine the Delphi2010 Datasnap technology with the Heartbeat pack feature! Please follow
(5)-Establishment of a stable service program for the use of TCP heartbeat packets
In order to make our service procedures more stable, some detail problems must be solved. As mentioned in the previous talk of the client unplug the network cable, causing TCP to become a dead connection on the server, if the number of dead connections, the server can be long-term stable operation is a huge threat.
In addition, after testing, if there is a TCP connection on the server, then the service program connects to the database, which will also produce a dead connection. This also poses a threat to the database server. Therefore, the server program written good or bad, directly affect the stability of the system!
How to solve the problem of TCP dead connection, there are many methods, the most effective is the heartbeat packet technology.
We add the heartbeat package code to the OnConnect event in Dsserver
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
Observing the above code, we put the heartbeat packet on the server to execute, if a TCP connection to the servers in 5 seconds did not receive data, will send to the peer to send heartbeat packet, 3 seconds interval, continuous send 5 times (the parameters are detailed in the previous talk Advanced Technology 4). The server ends the TCP connection if it is not answered 5 times later on the peer. TCP connections can be viewed using the netstat-p TCP command.
When the TCP is finished, the service program that Delphi writes will automatically end and connect 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
Now the server's TCP dead connection and the database dead connection are cleared, our system will be able to run stably for a long time.
(6)-Enhance the control ability of the service procedure to the visitor
1) As a service program, if you do not limit the number of client access, the consequences will be very scary. If someone does a spoof, the server is overwhelmed, the memory runs out, and the final server goes down. How do you limit the number of visitors?
We can set a variable to record the number of visitors, if more than our established number, then the subsequent connection server requests, will be broken off.
2) Limit the number of visits, but if not password authentication, unrelated personnel will be able to log on to the server! The workaround is for the client to pass in the user name and password, and if the user name and password are incorrect, the connection will be hung up.
Set the user name and password driver the username and password attributes of the taxonomy in the client's SQLConnection1.
3) Try not to set the MaxThreads property of the DSTCPServerTransport1, as well as the database connection pool is not set, delphi2010 will have a memory leak, the two parameters are saved by default.
Add the following code in the OnConnect event of the Dsserver1 control (using a TCP/IP connection):
Procedure Tmainform.dsserver1connect (dsconnecteventobject:tdsconnecteventobject);
var
val:tcp_keepalive;
Ret:integer;
clientconnection:tidtcpconnection;
begin //maximum number of connections, verify the visitor password
if (dsconnecteventobject.channelinfo = nil) or (Connections ; = $) or (Dsconnecteventobject.connectproperties[tdbxpropertynames.username] <> ' Sunstone ') or (Dsconnecteventobject.connectproperties [ Tdbxpropertynames.password] <> ' mypassword ') then
Begin
DSConnectEventObject.DbxConnection.Destroy; //Clientconnection.disconnect;
End
Else
begin //Get Socket connection clientconnection: = TI Dtcpconnection (DSCONNECTEVENTOBJECT.CHANNELINFO.ID);
clientconnection.ondisconnected: = clientdisconnectevent;
Record number of visitors
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//[TDBXPro Pertynames.serverconnection];
Set the heartbeat packet 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, ni L);
End
End
(7) Lifecycle life cycle of-tdsserverclass three attribute description
Lifecycle three types of properties: Session, Invocation, Server
These three kinds of properties are used in what circumstances, there is nothing to note, Delphi2010 rarely explained.
If you mess with these three kinds of properties, your service program may crash, data chaos, memory consumption, low efficiency issues!
Here I describe the use of these three attributes:
1. Session
Description: This is the default property in Delphi2010 and is also the Delphi recommended setting. The session creates a thread instantiation for each link from the client. What is the concept of instantiation? It is this thread that sets up all the classes, functions, and so on that you are going to use, and waits for your clients to use them directly. This thread and instantiation are not released until the client interrupts the connection. If there are 300 clients, then your server will have 300 threads and instances, a test for server hardware and memory.
Applicable environment: This setting is thread-safe!
The number of clients is small, each server does not exceed the number of connections: x x number of CPUs × (x0.7 per CPU) (This is the experience, the number of stable connections, not the limit quantity, do not misunderstand ^_^), memory is now very cheap, want to add how big! The client frequently invokes server data, preferably with this setting, regardless of the number of connections. If there are many clients, it is recommended to use load balancing and multiple servers to resolve them. 2. Invocation
Note: The server just establishes the connection, but does not instantiate first, only when the client requests the function, the server only then threads and instantiates, when the client runs out, the server releases the thread and the instance.
Applicable environment: This setting is thread-safe!
If the client calls the server data frequency is low, this method is very good, will save a lot of memory. 3. Server
Description: The server uses an instance of all client connections, not thread-safe. So you have to control the client's concurrent calls (you can use mutual exclusion, atomic weight, and so on), so that the client calls into a team to use the server resources.
Applicable environment: This setting is not thread-safe!!
Configuring a lower server server connection to the other end can only be a single-threaded mode of working
This article from the Delphi Garden, reproduced please indicate the source: http://www.delphifans.com/InfoView/Article_6521.html
Advanced Technology in Delphi2010 DATASNAP