Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 248
  • Last Modified:

Socket/Application Server

Hi everyone

I've built a socket/app server using indy 9.x (it has to be crossplatform capable).  It works fine on both Windows and Linux.  When a client connects a thread get spawned that deals with the request etc.

My server does the following:  A client connects via tcp socket sending a request (just a pipe delimited string at this point with the request command and data), the server creates the thread, parses the request and in a critical section does the action i.e. lookup a some data or creates a encrypted code etc. and then writes the result back to the client.

Everything works great except that the response time is on avg 6 - 7 requests that can be processed per second.  Embedding the functionality into the client get's a response of 30-60 transactions per sec.  I know it will be slower but by this margin?  Am I doing something wrong or is this the nature of the beast?

I cannot embed it in a client as applications written in anything from Java, Delphi, C++, VB, C# to Perl etc must be able to connect and use it.

Is there a better way of doing this kind of thing?

Please help

0
shokotah
Asked:
shokotah
  • 4
  • 4
1 Solution
 
pcsentinelCommented:
Why do you create a thread? The Indy server treats each connection as its own thread anyway?

Do you have to have a critical section in order to process the requested info. Try to operate within the thread wherever possible. If you need to send notifications you can do this using sendmessage etc.

regards
0
 
shokotahAuthor Commented:
Just to confirm/clear things up.  When I said create a thread I meant that Indy takes car of this.  I just thought I'd put it in to explain the process.  Sorry for the misunderstanding.

Here are some snippets:

procedure TServSockThread.IATCPExecute(AThread: TIdPeerThread);
var
  command, t: string;
  reply: string;
begin
  command := AThread.Connection.WaitFor('*---*');
  try
    cs.Acquire;
    ProcessRequest(AThread.Connection.Socket.Binding.PeerIP + '|' + command, reply);  //this may take some time
    AThread.Connection.Writeln(reply);
    cs.Release;
  except
    AThread.Connection.Writeln(err900 + sockTerm);
  end;
end;

procedure TServSockThread.ProcessRequest( Request: string; var Reply: string );
var
  command, t: string;
begin
  command := Request;
  Reply := '';

  if (Length(Trim(command)) <> 0) then begin
    try
      Parse(command); //parses the command e.g. "3010|kjdajhs2uej|get_info:somedata|somedata|somedata*---*"
    except
      if not (iarequest.parsed) then begin
        Reply := iarequest.error + sockTerm;
        Exit;
      end;
    end; //except
    if not (iarequest.parsed) then begin
      Reply := iarequest.error + sockTerm;
      Exit;
    end;
  end
  else begin
    Reply := err500 + sockTerm;
    Exit;
  end;

  case iarequest.instruction of
    isGetInfo        : begin                              
                                Reply := GetInfoFunction(somedata_requested);
                            end;
    ......
  end;
end;


Hope this helps.


0
 
pcsentinelCommented:
Ok, but why to you need a critical section.

I am presuming because the GetInfoFunction is using a datacontrol or someting like that.

What you can do is to create the data controls in the onconnect of the server, destroy it in the ondisconnect and use it just for that connection.

The trouble with critical sections is that if your server is busy then it can take quite some time for it to become available.

regards

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
shokotahAuthor Commented:
Yes, the GetInfoFunction contains code to look data up in a data table and restruture it etc, which is not exactly thread safe/multi thread capable.  I'm using sqlite as the db backend which is not threadsafe as I understand it.

If I create/connect to the datasource in the onconnect event will that not cause problems with the other threads or is the onconnect per thread specific(?) i.e. once the onconnect event is fired any controls/bindings etc created will only be applicable for the thread specified in AThread parm?

0
 
shokotahAuthor Commented:
Also before I had the critical section there, as soon as a second/third client app starts hitting the server it crashed.
0
 
pcsentinelCommented:
Yes the onconnect is thread specific i.e. using AThread. So this shouldn't cause problems with other threads.

But if you consider that you db connection isn't thread safe thenyou don't have any other choice.

I suggest you try doing a test.

Create a long running query, then connect from say 3 client apps and run the query. Make sure the queries will return different data so you can be sure your getting the right data back.

See what happens

regards
0
 
shokotahAuthor Commented:
Thanks for your help.  I'll give it a try.  

Is there perhaps any other way I can do what I need.  I.e. expose functions as with COM but not using COM i.e. create an API for the app server?
0
 
pcsentinelCommented:
Well yes you could put it into a Com Server or palind old dll which will work fine for delphi,c# c++ VB but I can't comment on Perl sorry

regards
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now