RTC Forums

Subscription => Support => Topic started by: Cesar on September 01, 2016, 11:01:13 PM



Title: TCP Established connections remain open
Post by: Cesar on September 01, 2016, 11:01:13 PM
Hi,

I'm using TRtcHTTPServer to serve an image file. This server has to attend thousands of requests per minute.  As requests are served the total connection count rises.  In the windows monitor the TCPv4 Established Connections count also goes up.

There is a point around 4,000 Established connections in which the number of connections does not decrease once the requests stop.  The number of connection goes down until the server program is closed.

I'm using RTC version 7.28,  Delphi XE7, and I've tried it in windows 7, 10 and Server 2012 all with the same result.

I don't know how to attach a file.  I created a very simple project that reproduces the issue.  I'm pasting it here. As for the image I'm using a 9KB JPEG.

The test goes like this.

1. Load the image
2. Start the server
3. Stress the server making requests from one or several machines, with a few dozens of threads.
4. Monitor the established connections
5. When the number of connections gets around 4 to 5 thousand stop the requests.
6. Wait for the number of connections to fall after the TCPWaitTimeout

The TCPWaitTimeout is set to 30 seconds in the Registry.

Please let me know if this info is enough. 

Appreciate your help.

>>>> START OF CODE

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, rtcDataSrv, rtcInfo, rtcConn, rtcHttpSrv;

type
  TForm1 = class(TForm)
    RtcHttpServer1: TRtcHttpServer;
    RtcDataProvider1: TRtcDataProvider;
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure RtcDataProvider1CheckRequest(Sender: TRtcConnection);
    procedure RtcDataProvider1DataReceived(Sender: TRtcConnection);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  fileString : string;

implementation


{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  fStream : TFileStream;
  sStream : TStringStream;
begin
     if OpenDialog1.Execute then begin
        fStream:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
        sStream:=TStringStream.Create;

        sStream.CopyFrom(fStream, fStream.Size);
        fileString:=sStream.DataString;

        sStream.Free;
        fStream.Free;
        ShowMessage('File loaded!');
     end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
     RtcHTTPServer1.ServerAddr:='';
     RtcHTTPServer1.ServerPort:=Edit1.Text;
     RtcHTTPServer1.Listen;
end;

procedure TForm1.RtcDataProvider1CheckRequest(Sender: TRtcConnection);
begin
     TRtcDataServer(Sender).Accept;
end;

procedure TForm1.RtcDataProvider1DataReceived(Sender: TRtcConnection);
begin
     with TRtcDataServer(Sender) do begin
          if request.Complete then begin
             TRtcDataServer(Sender).Write(fileString);
          end;
     end;
end;

end.

<<<< END OF CODE


Title: Re: TCP Established connections remain open
Post by: D.Tkalcec (RTC) on September 02, 2016, 05:48:48 AM
1. HTTP clients do not have to close their connections when they stop sending requests, unless you explocitly tell them to.
2. If the network is flooded, chances are high that random packets will be dropped. Since a TCP connection is a negotiatiom between Clients and the Server, even closing a connection gracefully requires packets to be sent from one side to the other and back. If these packet get dropped, connections can remain "open" for hours. To avoid this, you can use the Timeouts property on the Server and on the Client to have idle connections closed after some time of inactivity.

Best Regards,
Danijel Tkalcec


Title: Re: TCP Established connections remain open
Post by: Cesar on September 05, 2016, 04:27:01 PM
Thank you.  That seems to work correctly  :)