A doubt using sockets

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

A doubt using sockets

Postby mark_c » Tue Jun 23, 2015 1:27 am

hello,
I need a confirmation about windows sockets. I have read that using sockets in blocking mode, for each new clients that connects to the server, automatically creates new thread so that each client can communicate with the server without any blocks and so I ask you:

a) I get it right?
b) is a property of windows socket?
c) is a property of TserverSocket?
d) it is true, with blocking sockets, that if a client is blocked for any reason other clients connected to the server continue to receive data?

thanks
mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am

Re: A doubt using sockets

Postby rlebeau » Tue Jun 23, 2015 8:06 pm

mark_c wrote:I have read that using sockets in blocking mode, for each new clients that connects to the server, automatically creates new thread so that each client can communicate with the server without any blocks and so I ask you:

a) I get it right?
b) is a property of windows socket?
c) is a property of TserverSocket?
d) it is true, with blocking sockets, that if a client is blocked for any reason other clients connected to the server continue to receive data?


a) Almost

b) NO, it is not a property of the underlying socket.

c) TServerSocket DOES create a new thread for each client, but only when its ServerType property is set to stThreadBlocking. In that mode, its OnGetThread event (if assigned) allows you to create your own custom thread class derived from TServerClientThread if you want to handle I/O operations your own way. If you do not assign an OnGetThread handler, or if it returns nil, a default thread class is used which simply triggers the server's OnClientRead, OnClientWrite, and OnClientError events.

d) If the clients are running in their own threads, yes.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1648
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: A doubt using sockets

Postby mark_c » Thu Jun 25, 2015 4:12 am

The purpose of this code below is exclusively didactic.

When ServerSocket1-> ServerType is set to stThreadBlocking; and I display the number of active threads of my process with the Resource Monitor tool of windows and I execute some instances of putty.exe, I see that the number of running threads increases, but that thread are there?
Are thread ghost and "empty" instantiated from TServerSocket by default?

if I repeat the same experiment by setting ServerSocket1-> ServerType = stNonBlocking; the number of active threads of my process remains unchanged example 3: why?

thanks

Code: Select all
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"

void SendMyData(char *msg);
bool bAbort;

DWORD WINAPI ThreadTest( LPVOID lpParameter );
DWORD ID1;
HANDLE test;


//---------------------------------------------------------------------------

#pragma link "Grids"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
        //ServerSocket1->ServerType=stThreadBlocking;
        ServerSocket1->ServerType=stNonBlocking;
        ServerSocket1->Port = 5000;
        ServerSocket1->Active = True;
 }
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        bAbort = true;
        if(test) TerminateThread(test,0);
        Form1->Caption = "Stopped.....";

}
//---------------------------------------------------------------------------

void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
        if (ErrorCode == 10053) {
                Socket->Close();
        }

        ErrorCode = 0;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        bAbort = false;
        test = CreateThread(NULL,0,ThreadTest,Form1->Handle,0,&ID1);
        Form1->Caption = "Started.....";
}
//---------------------------------------------------------------------------

DWORD WINAPI ThreadTest( LPVOID lpParameter )
{
        while(!bAbort)
        {
                SendMyData("ABCDEFGHIKJLMNOPQRSTUVWXYZ0123456789");
                Sleep(100);
        }

        return 0;
}
//---------------------------------------------------------------------------

void SendMyData(char *msg)
{       
        try{
                /*
                for(int actconn = 0; actconn < Form1->ServerSocket1->Socket->ActiveConnections; actconn++)
                {
                        Form1->ServerSocket1->Socket->Connections[actconn]->SendText(msg);
                }
                */
                Form1->ServerSocket1->Socket->Connections[0]->SendText(msg);
        } catch(...) { }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
        ServerSocket1->Active = false;       
}
//---------------------------------------------------------------------------








mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am

Re: A doubt using sockets

Postby rlebeau » Mon Jun 29, 2015 7:24 pm

mark_c wrote:When ServerSocket1-> ServerType is set to stThreadBlocking; and I display the number of active threads of my process with the Resource Monitor tool of windows and I execute some instances of putty.exe, I see that the number of running threads increases, but that thread are there?
Are thread ghost and "empty" instantiated from TServerSocket by default?


A new thread is created (if thread pooling is disabled, which it is by default) when a client is accepted by the server. I explained that in my previous reply. Yes, in stThreadBlocking mode, TServerSocket creates its own worker threads to manage accepted clients.

mark_c wrote:if I repeat the same experiment by setting ServerSocket1-> ServerType = stNonBlocking; the number of active threads of my process remains unchanged example 3: why?


stNonBlocking mode does not use worker threads for managing accepted clients. The OnClient... events are triggered by window messages that are generated by client socket activity (each client TCustomWinSocket object creates a hidden window for itself to receive those messages). So the thread that activates TServerSocket needs to have an active message loop. Which is the main UI thread in your example, so the main UI message loop handles the messages, so you don't have to do anything extra to enable that behavior.
Last edited by rlebeau on Tue Jun 30, 2015 1:18 pm, edited 1 time in total.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1648
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: A doubt using sockets

Postby mark_c » Tue Jun 30, 2015 2:03 am

thanks, but I can not understand what is "duplicate" of my thread. Using the socket in blocking mode, I noticed that the number of threads increases with the number of clients that connect to the server, but if a client freezes other clients no longer receive data: why?

There is a book that explains in detail this part of the programming environment Borland C ++ Builder?

tankyou







p.s.

I fear that you understand, I did not use the event OnClientRead and OnClientWrite, events that are made available automatically for each thread instantiated by the server when using the socket to blocking mode.


Description

Set ServerType to stThreadBlocking to automatically spawn a new thread for each socket connection accepted by the server socket. When ServerType is stThreadBlocking, the execution of the connection thread is suspended while reading or writing until all information has been transferred over the connection. The thread for each connection generates OnClientRead or OnClientWrite events when the server socket needs to read or write.
mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am

Re: A doubt using sockets

Postby rlebeau » Tue Jun 30, 2015 1:24 pm

mark_c wrote:Using the socket in blocking mode, I noticed that the number of threads increases with the number of clients that connect to the server


As it should be.

mark_c wrote:if a client freezes other clients no longer receive data: why?


You have to be doing something wrong in your code that is serializing the threads. Please show the actual code that is freezing.

mark_c wrote:I fear that you understand, I did not use the event OnClientRead and OnClientWrite, events that are made available automatically for each thread instantiated by the server when using the socket to blocking mode.


That is just the default behavior. You can optionally derive a custom class from TServerClientThread and overriding its virtual DoClientExecute() method, and then return an instance of that class in the TServerSocket::OnGetThread event. Then the thread can do whatever it wants. You do not have to use the OnClient... events if you do not want to.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1648
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: A doubt using sockets

Postby mark_c » Tue Jun 30, 2015 10:52 pm

rlebeau wrote:
You have to be doing something wrong in your code that is serializing the threads. Please show the actual code that is freezing.



the code is the same as what I posted; the cause might be because I used CreateThread instead of TThread?

thanks
mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am

Re: A doubt using sockets

Postby rlebeau » Wed Jul 01, 2015 1:04 pm

mark_c wrote:the code is the same as what I posted


There is no possible way that the code you have shown can be freezing ANY of the client threads, as those threads are not even doing anything at all, they are just sitting idle. You are sending data from YOUR OWN thread that is running independent of the server's client threads. You said there is a client freezing, but you are not doing anything to freeze any specific client thread. However, if a client is frozen on ITS end, YOUR thread will freeze when that client's outbound buffer fills up, and that WOULD prevent other clients from receiving new data because you are doing all of your sending from the context of YOUR thread and not from the context of the individual client threads, like you should be.

Do something more like this instead:

Code: Select all
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma link "Grids"
#pragma resource "*.dfm"
TForm1 *Form1;
bool bAbort = false;

class TMyClientThread : public TServerClientThread
{
private:
    void SendMyData(char *msg);
protected:
    void __fastcall ClientExecute();
public:
    __fastcall TMyClientThread(TServerClientWinSocket *ASocket);
};

__fastcall TMyClientThread::TMyClientThread(TServerClientWinSocket *ASocket)
    : TServerClientThread(false, ASocket)
{
}

void TMyClientThread::SendMyData(char *msg)
{     
    ClientSocket->SendText(msg);
}

void __fastcall TMyClientThread::ClientExecute()
{
    while ((!Terminated) && (ClientSocket->Connected))
    {
        if (!bAbort)
            SendMyData("ABCDEFGHIKJLMNOPQRSTUVWXYZ0123456789");
        Sleep(100);
    }
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
        ServerSocket1->ServerType = stThreadBlocking;
        ServerSocket1->Port = 5000;
        ServerSocket1->Active = True;
 }
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        bAbort = true;
        Form1->Caption = "Stopped.....";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1GetThread(TObject *Sender,
    TServerClientWinSocket *ClientSocket, TServerClientThread* &SocketThread)
{
    SocketThread = new TMyClientThread(ClientSocket);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
    Socket->Close();
    ErrorCode = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        bAbort = false;
        Form1->Caption = "Started.....";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    ServerSocket1->Active = false;       
}
//---------------------------------------------------------------------------


mark_c wrote:the cause might be because I used CreateThread instead of TThread?


No. But you are mishandling your socket communication with the clients in stThreadBlocking mode.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1648
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: A doubt using sockets

Postby mark_c » Thu Jul 02, 2015 2:28 am

I had understood that the creations of 'n' thread was a feature of the VCL and that it was not necessary to use calls like: SocketThread = new TMyClientThread (ClientSocket); to instantiate new threads

thankyou
mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am

Re: A doubt using sockets

Postby rlebeau » Thu Jul 02, 2015 12:33 pm

mark_c wrote:I had understood that the creations of 'n' thread was a feature of the VCL and that it was not necessary to use calls like: SocketThread = new TMyClientThread (ClientSocket); to instantiate new threads


Only if you make use of the OnClientRead/OnClientWrite events, in which case you can utilize the default threads that TServerSocket creates internally by default. But your code example was not using those events, so you should create your own thread class to manage your socket I/O properly.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1648
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: A doubt using sockets

Postby mark_c » Fri Jul 03, 2015 11:04 am

There is a tutorial that explains step by step and in detail how to build a server that instance a separate thread for each client that connects to the server?

thanks
mark_c
BCBJ Master
BCBJ Master
 
Posts: 200
Joined: Thu Jun 21, 2012 1:13 am


Return to Technical

Who is online

Users browsing this forum: No registered users and 6 guests

cron