Board index » delphi » Error 10055 bug in TClientSocket?

Error 10055 bug in TClientSocket?

If you take this simple "program":

   procedure TForm1.Timer1Timer(Sender: TObject);
   begin
     ClientSocket1.Close;
     ClientSocket1.Open;
   end;

   procedure TForm1.ClientSocket1Error(Sender: TObject; Socket:
TCustomWinSocket;
     ErrorEvent: TErrorEvent; var ErrorCode: Integer);
   begin
     ErrorCode:=0;
   end;

All it does, is connecting to a non-existing server every second and
ignore all errors. This should work, shouldn't it? But for some reason
you will start getting an error 10055 after about 1 hour (on a win2k
machine). When you run 'netstat -na' on the command prompt you will see
hundreds of sockets open in the LISTEN state. Somehow they don't get
closed after an error. You can't close them yourself, because a call to
TClientSocket.Close is ignored when the socket is not connected (line
1949-1954 in ScktComp.pas):

   if (Value <> FClientSocket.Connected) and
      not (csDesigning in ComponentState) then
   begin
     if FClientSocket.Connected then
       FClientSocket.Disconnect(FClientSocket.FSocket)
     else FClientSocket.Open(FHost, FAddress, FService,
                        FPort, ClientType = ctBlocking);
   end;

FClientSocket.Disconnect frees the socket on the API-level, but it is
never called after an error. The only way to free the socket after an
error is to destroy the entire TClientSocket. To fix this problem, I've
inserted "Disconnect(FSocket);" at line 655 of ScktCompt.pas after the
call to the event handler and it seems to solve the problem, but I don't
know if this has some unwanted side effects. My program seems to work fine.

Is this really a bug in TClientSocket? If so, where can I report it to
Borland?

Emond Papegaaij

 

Re:Error 10055 bug in TClientSocket?


Quote

>    procedure TForm1.Timer1Timer(Sender: TObject);
>    begin
>      ClientSocket1.Close;
>      ClientSocket1.Open;
>    end;

>    procedure TForm1.ClientSocket1Error(Sender: TObject; Socket:
> TCustomWinSocket;
>      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
>    begin
>      ErrorCode:=0;
>    end;

> All it does, is connecting to a non-existing server every second and
> ignore all errors. This should work, shouldn't it? But for some reason
> you will start getting an error 10055 after about 1 hour (on a win2k
> machine). When you run 'netstat -na' on the command prompt you will see
> hundreds of sockets open in the LISTEN state.

I saw similar strange netstat results on Win2000 (terminal server installed) - hundreths of sockets in LISTEN state - but I think the sockets were not really opened. It means I would not belive the netstat report too much.

About your problem:
 - did you try to  increase efemeral port limit I mentioned in my previous message? Search msdn.microsoft.com for "10055" keyword
- there is what happens probably
   If you create a socket each second and then try to conenct the socket to nonexisting server then  the socket should be in "ACK sent" state for long time (until conenction timeout expires). I think it can take up to 15 minutes (if there is no router which returns an ICM error message to you - for example ICM__HostUnreacheble or ICMP_NetworkUnreachable). Even if you close the socket the conenction process will not be interrupted immediately.
It means after 1 hour you can have 3600 socket created (if I assume the timeout is larger than 15 minutes or the socket is not closed at all) and not closed. Because WinNT/2000 allows to open efemeral sockets(socket with port numbers higher than 1023) with port number less than 5000 you can open about 4000 (5000-1023) sockets. It looks like your application uses all free dynamic port numbers so the TCP/IP stack starts report 10055 errors.
The solution should be: increase efemeral port limit and don't create so much connections. You can decrease conenction timeout too (using registry values) but it is not recommended method. WInSock1.X doesn't allow to change the timeout on socket basis. I am not sure whether WinSock 2.X supports it or not.

Quote
>Somehow they don't get
> closed after an error. You can't close them yourself, because a call to
> TClientSocket.Close is ignored when the socket is not connected (line
> 1949-1954 in ScktComp.pas):

It could explain the problem, I think.

- Show quoted text -

Quote

>    if (Value <> FClientSocket.Connected) and
>       not (csDesigning in ComponentState) then
>    begin
>      if FClientSocket.Connected then
>        FClientSocket.Disconnect(FClientSocket.FSocket)
>      else FClientSocket.Open(FHost, FAddress, FService,
>                         FPort, ClientType = ctBlocking);
>    end;

> FClientSocket.Disconnect frees the socket on the API-level, but it is
> never called after an error. The only way to free the socket after an
> error is to destroy the entire TClientSocket. To fix this problem, I've
> inserted "Disconnect(FSocket);" at line 655 of ScktCompt.pas after the
> call to the event handler and it seems to solve the problem, but I don't
> know if this has some unwanted side effects. My program seems to work fine.

> Is this really a bug in TClientSocket? If so, where can I report it to
> Borland?

Note: The best way to properly handle TCP/IP connections is to use no components. It is the only way which allow you to have full control.

Regards
Dalibor Toman

Re:Error 10055 bug in TClientSocket?


Emond,

Quote
>    procedure TForm1.Timer1Timer(Sender: TObject);
>    begin
>      ClientSocket1.Close;
>      ClientSocket1.Open;
>    end;

I had a similar problem.  I fixed it by closing the socket this way:

ClientSocket1.Socket.Close;

--
Regards,
Paul Breneman
http://www.BrenemanLabs.com

Other Threads