0
votes

I have client-server system that uses DataSnap. I want to log the client application data so I use the TDSServer - OnConnect Event. In this event I can access what I want with the following code:

IP:= DSConnectEventObject.ChannelInfo.ClientInfo.IpAddress  
ClientPort:= DSConnectEventObject.ChannelInfo.ClientInfo.ClientPort  
Protocol:= DSConnectEventObject.ChannelInfo.ClientInfo.Protocol  
AppName:= DSConnectEventObject.ChannelInfo.ClientInfo.AppName  

first 3 lines are OK but AppName is empty!!!

(I run server and client on the same computer i.e. localhost)

1

1 Answers

3
votes

I have been unable to find any online information about how to specify the AppName when the client connects via TCP/IP. If you look at the code

procedure TDSTCPChannel.Open;
var
  ClientInfo: TDBXClientInfo;
begin
  inherited;
  FreeAndNil(FChannelInfo);
  FChannelInfo := TDBXSocketChannelInfo.Create(IntPtr(FContext.Connection), FContext.Connection.Socket.Binding.PeerIP);

  ClientInfo := FChannelInfo.ClientInfo;

  ClientInfo.IpAddress := FContext.Connection.Socket.Binding.PeerIP;
  ClientInfo.ClientPort := IntToStr(FContext.Connection.Socket.Binding.PeerPort);
  ClientInfo.Protocol := 'tcp/ip';

  FChannelInfo.ClientInfo := ClientInfo;
end;

in DataSnap.DSTCPServerTransport.Pas it is evident that the ClientInfo.AppName is not set.

However, the following work-around works with the Seattle demo DataSnap Basic Server + Client:

  1. In the client, add a Param 'AppName' to the SqlConnection1 component's Params and set its value to something like 'MyTestApp'. Recompile the client.

  2. Open the server in the IDE and modify the ServerContainerForm's code as shown below.

Code:

uses
   [...], DBXTransport;

procedure TForm8.DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
var
  S : String;  //  added
  Info : TDBXClientInfo;  //  added
begin
   ActiveConnections.Insert;
   if DSConnectEventObject.ChannelInfo <> nil then
   begin
     ActiveConnections['ID'] := DSConnectEventObject.ChannelInfo.Id;
     ActiveConnections['Info'] := DSConnectEventObject.ChannelInfo.Info;
   end;
   ActiveConnections['UserName'] := DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName];
   ActiveConnections['ServerConnection'] := DSConnectEventObject.ConnectProperties[TDBXPropertyNames.ServerConnection];
   ActiveConnections.Post;

   InsertEvent('Connect');

   //  following added to get AppName from client

   S := DSConnectEventObject.ConnectProperties['AppName'];
   Info := DSConnectEventObject.ChannelInfo.ClientInfo;
   Info.AppName := S;

   DSConnectEventObject.ChannelInfo.ClientInfo := Info;
   Caption :=  DSConnectEventObject.ChannelInfo.ClientInfo.AppName;
end;

As you can see, it works by picking up the value set for AppName in the client's SqlConnection1.Params in the call to `DSConnectEventObject.ConnectProperties['AppName']' and then display it on the Caption of the ServerContainerForm.

Obviously, you could pass any other name/value pair by adding them to the SqlConnection's Params on the client and then pick them up on the server by calling DSConnectEventObject.ConnectProperties[].