Page 1 of 2

Trap socket error 10055

PostPosted: Fri Dec 20, 2019 2:42 am
by mark_c
hello,
i writed a simple Client wich try four port range (80, 8081, 5000, 8345) and ip range from 100.45.67.89 to 200.234.34.234
The sequence operations are following:
1) set ip address
2) set port number
3) try connection
if connection ok
4) close connection and set next port number
a the end of port range, set next ip range and so on
if no success
5) try next port range number
a the end of port range, try next ip range adress

Well, some time I get socket error 10055 by i don't know how to trap this.

I found a short example that captures the 10055 exception with Listen, but for me it is incorrect to use it in BCB6, is there another way to capture the 10055 error?

Code: Select all
try
{
  IPEndPoint localEndPoint;
  localEndPoint = new IPEndPoint(IPAddress.Any,listenPort);

  sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
  sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger,1);
  sock.SetSocketOption(SocketOptionLevel.Tcp,SocketOptionName.NoDelay,1);

  sock.Bind(localEndPoint);
  sock.Listen(128); // <--- SocketException
  sock.BeginAccept(new AsyncCallback(Callback),sock);
}
catch (SocketException socketException)
{

}


note: socket is set nonblocking

Re: Trap socket error 10055

PostPosted: Fri Dec 20, 2019 3:43 pm
by rlebeau
Please show YOUR actual code that you are having trouble with. It likely has a bug in it. But we can't see what that is. Posting someone else's workaround code is useless without context.

Re: Trap socket error 10055

PostPosted: Sat Dec 21, 2019 1:39 am
by mark_c
no problem, original code it's similar 100% to this code.
Error 10055 occurs after many hours, and no for obvious reason.

thank you


Code: Select all
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit1.h"
bool isopen;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   AnsiString myip;
   Memo1->Clear();

   for( int g=1; g<255;g++ )
   {
      for( int i=1; i<255;i++ )
      {
         if(ClientSocket1->Active)
            ClientSocket1->Close();
         
         myip.sprintf("1.1.%d.%d",g, i);

// In this example the pot is deliberately kept fixed
// I don't think that's the problem is here
// error 10055 occurs after many hours, and no for obvious reason

         ClientSocket1->Host=myip;
         ClientSocket1->Port=80;
         ClientSocket1->Open();

         while(isopen)
         {
            Sleep(20);
            Application->ProcessMessages();
            Caption=myip;
         }
      }
   }
   Button1->Enabled=true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientSocket1Error(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Memo1->Lines->Add(ErrorCode);
   ErrorCode = 0;
   isopen=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Lookup(TObject *Sender,
TCustomWinSocket *Socket)
{
   isopen=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
   isopen=false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
TCustomWinSocket *Socket)
{
   isopen=false;
}
//---------------------------------------------------------------------------

Re: Trap socket error 10055

PostPosted: Sun Dec 22, 2019 3:02 am
by rlebeau
mark_c wrote:no problem, original code it's similar 100% to this code.
Error 10055 occurs after many hours, and no for obvious reason.


Have a look at these past discussions:

http://www.delphigroups.info/2/cc/193138.html

https://stackoverflow.com/questions/47158231/

In a nutshell, you need to call Socket->Close() in the OnError event:

Code: Select all
void __fastcall TForm1::ClientSocket1Error(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Memo1->Lines->Add(ErrorCode);
   ErrorCode = 0;
   Socket->Close(); // <-- HERE
   isopen=false;
}


That being said, you really should NOT be using a ProcessMessages() loop at all. If you are using the socket in non-blocking mode (the default), you should re-write the code to be truly event driven and get rid of the blocking loop altogether, eg:

Code: Select all
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int g, i;
AnsiString myip;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Button1->Enabled = false;
   g = 0;
   i = 255;
   myip = "";
   Memo1->Clear();
   NextIP();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::NextIP()
{
   if (i == 255)
   {
      if (g == 255)
      {
         Button1->Enabled = true;
         return;
      }
      ++g;
      i = 1;
   }
   else
      ++i;

   myip.sprintf("1.1.%d.%d", g, i);
   Caption = myip;

   ClientSocket1->Host = myip;
   ClientSocket1->Port = 80;
   ClientSocket1->Open();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Error(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Memo1->Lines->Add(ErrorCode);
   ErrorCode = 0;
   Socket->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket)
{
   Socket->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender, TCustomWinSocket *Socket)
{
   NextIP();
}
//---------------------------------------------------------------------------


Otherwise, set the socket to blocking mode and get rid of ProcessMessages() completely, and the event handlers, you won't need them anymore:

Code: Select all
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Button1->Enabled = false;

   AnsiString myip;
   Memo1->Clear();

   for (int g = 1; g < 255; ++g)
   {
      for (int i = 1; i < 255; ++i)
      {
         myip.sprintf("1.1.%d.%d",g, i);
         Caption = myip;
         Update();

         ClientSocket1->Host = myip;
         ClientSocket1->Port = 80;

         try
         {
            ClientSocket1->Open();
         }
         catch (const Exception &e)
         {
            Memo1->Lines->Add(e.Message);
         }

         ClientSocket1->Close();
      }
   }

   Button1->Enabled = true;
}
//---------------------------------------------------------------------------


In this case, it would be better to move the TClientSocket operations to a worker thread that posts status updates to the UI thread when needed.

Re: Trap socket error 10055

PostPosted: Sun Dec 22, 2019 6:34 am
by mark_c
thanks remy,
however as you saw, before opening a socket I always check that it is not already open and if so I close it:

Code: Select all
          if (ClientSocket1->Active)
             ClientSocket1->Close();


is this control not enough in case of socket error?

Re: Trap socket error 10055

PostPosted: Wed Jan 08, 2020 6:43 am
by mark_c
I have a problem: supposing I want to instantiate 100 threads with the above code and thus have 100 simultaneous TCP connections, how do I handle the OnConnect event for 100 threads?
I think there would be a race condition problem, am I wrong?
Do I need to find a way to sync this event?

Re: Trap socket error 10055

PostPosted: Wed Jan 08, 2020 11:32 am
by rlebeau
You would have to create 100 TClientSocket objects, each with an OnConnect handler assigned. Best to have each thread create its own TClientSocket object. You can use a single method for all 100 events, such as a method of the thread class. You can use the event's Sender parameter to know which TClientSocket object is firing the event. You don't need to sync the events unless they access resources that are shared across threads, or if they need to make UI updates.

Re: Trap socket error 10055

PostPosted: Wed Jan 08, 2020 12:34 pm
by mark_c
so use a single socket for 100 threads, the socket created statically by the main thread at runtime to understand and share it would be wrong, right?
This is because the various threads in execution would remain in the queue waiting for their turn to access the only shared socket; in this case then, I should synchronize every access to the socket, right?

Re: Trap socket error 10055

PostPosted: Wed Jan 08, 2020 4:51 pm
by rlebeau
mark_c wrote:so use a single socket for 100 threads, the socket created statically by the main thread at runtime to understand and share it would be wrong, right?


For 100 TCP connections, you would need 100 sockets. Each thread would have its own socket that it manages separate from every other thread.

mark_c wrote:This is because the various threads in execution would remain in the queue waiting for their turn to access the only shared socket; in this case then, I should synchronize every access to the socket, right?


No, not even close.

Re: Trap socket error 10055

PostPosted: Thu Jan 09, 2020 3:30 am
by mark_c
sorry, ultimately, what I want to achieve is to have 100 threads running, each with its private socket and its events: is it possible?

Re: Trap socket error 10055

PostPosted: Sat Jan 11, 2020 3:02 am
by HsiaLin
Just curious, you aren't trying to make a Low Earth Orbit Ion Cannon are you?

Re: Trap socket error 10055

PostPosted: Sat Jan 11, 2020 3:23 am
by mark_c
HsiaLin wrote:Just curious, you aren't trying to make a Low Earth Orbit Ion Cannon are you?


:lol: :lol: :lol:
don't worry, they are only didactic experiments.

I'll give you an example: if you want to scan 2^32 internet addresses and for each one it takes 1 second, it would take 136 years to scan them all; we would already be beautiful than dead. So, the idea is to use either 136 computers and take 1 year or, 1 program with a certain number of threads and sockets.

I hope I have satisfied your curiosity?

When we have quantum computers at our disposal, these types of problems will no longer exist, let's be patient.

Re: Trap socket error 10055

PostPosted: Sun Jan 12, 2020 1:28 pm
by rlebeau
mark_c wrote:sorry, ultimately, what I want to achieve is to have 100 threads running, each with its private socket and its events: is it possible?


Yes, it is, exactly as I described earlier. Is there a particular issue you are having with understanding what I described? What have you actually tried that is not working for you?

And BTW, if you use TClientSocket inside a thread, it is best NOT to use events at all. Use the TClientSocket in thread-blocking mode instead. It will make writing the thread code much simpler. If you use TClientSocket in non-blocking mode in a thread, then you have to give each thread its own message loop, which is overkill if the threads don't have other elements that also need a message loop (UIs, STA COM objects, etc).

Re: Trap socket error 10055

PostPosted: Sun Jan 12, 2020 1:47 pm
by mark_c
sorry Remy if sometimes I repeat the same things, maybe the same as you said, but unfortunately I don't know much about multi-thread programming in addition to sockets, even almost for nothing.
However I started writing some code that now works, using precisely, as you suggested, blocking sockets because, as you say, they are easier to manage. I saw on the net your answer where you explained to a user the use of non-blocking sckets, where you answered that you have to create a loop that continuously reads the system messages and you have to act accordingly, for now it is too complex.
So, I use blocking sockets which are easier to manage.

Re: Trap socket error 10055

PostPosted: Tue Jan 14, 2020 2:11 pm
by rlebeau
mark_c wrote:sorry Remy if sometimes I repeat the same things, maybe the same as you said, but unfortunately I don't know much about multi-thread programming in addition to sockets, even almost for nothing.


This has less to do with threading, and more to do with general OOP design. You have a Thread class. Give it a TClientSocket data member, and create/destroy the TClientSocket inside the Thread class as needed. Then create 100 instances of your Thread class.