🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
15 messages
15 total messages Started by Josh Arnold Thu, 14 Sep 2006 00:17
TClientSocket OnRead event issues
#1931
Author: Josh Arnold
Date: Thu, 14 Sep 2006 00:17
25 lines
2013 bytes
Hello,

I have an application that acts as a client to a device running an embedded 
TCP/IP stack. The embedded device is the server and I'm trying to receive 
messages from the server.

I'm using BDS 2006 but not using the socket components from the tool 
pallete, instead I am using the TClientSocket component.  I open the socket 
and assign the OnRead event handler at run time. The server device properly 
receives any messages I send (I'm just sending text) and then replies back 
with the necessary data (again just text).

I can see the response when capturing with Ethereal. But the OnRead event 
does not fire in my client app therefore  my application never sees any of 
the responses from the server.

Here is the bizarre part.  I can run the Internet Chat example program from 
C++ Builder 5 on another machine and my app talks to it and receives from it 
just fine. AND I can use the Chat example program to talk to the embedded 
server device and it WILL see the responses from the server.  Both 
applications use the same TClientSocket component.

Any ideas anyone?????  I am quite stumped
thanks
-Josh 
Re: TClientSocket OnRead event issues
#1932
Author: Remy Lebeau (TeamB)
Date: Thu, 14 Sep 2006 00:32
26 lines
2163 bytes
"Josh Arnold" <jdaudio02@hotmail.com> wrote in message
news:4508a026@newsgroups.borland.com...

> I can see the response when capturing with Ethereal. But the OnRead
> event does not fire in my client app therefore  my application never
> sees any of the responses from the server.

Please show your actual code.  The only way you would not be receiving the
event is if the TClientSocket never received the notification in the first
place.  Since non-blocking sockets use the message queue, make sure that you
are not using anything that can discard messages before they are processed.

> I can run the Internet Chat example program from C++ Builder 5 on
> another machine and my app talks to it and receives from it just fine.
> AND I can use the Chat example program to talk to the embedded
> server device and it WILL see the responses from the server.  Both
> applications use the same TClientSocket component.

Then your failing application is not actually receiving any data from the
embedded server to begin with, despite what Ethereal says.  Ethereal sits at
a very low level.  Just because it says data is arriving at the TCP/IP layer
does not necessary mean that the data is reaching the application layer.


Gambit
Re: TClientSocket OnRead event issues
#1933
Author: Josh Arnold
Date: Thu, 14 Sep 2006 01:04
44 lines
2632 bytes
I will post code first thing tomorrow.

> Then your failing application is not actually receiving any data from the
> embedded server to begin with, despite what Ethereal says.  Ethereal sits 
> at
> a very low level.  Just because it says data is arriving at the TCP/IP 
> layer
> does not necessary mean that the data is reaching the application layer.

I agree, but the old example chat program works using the same TClientSocket 
component and nearly identical code.  Very strange!





"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4508a3f3$2@newsgroups.borland.com...
>
> "Josh Arnold" <jdaudio02@hotmail.com> wrote in message
> news:4508a026@newsgroups.borland.com...
>
>> I can see the response when capturing with Ethereal. But the OnRead
>> event does not fire in my client app therefore  my application never
>> sees any of the responses from the server.
>
> Please show your actual code.  The only way you would not be receiving the
> event is if the TClientSocket never received the notification in the first
> place.  Since non-blocking sockets use the message queue, make sure that 
> you
> are not using anything that can discard messages before they are 
> processed.
>
>> I can run the Internet Chat example program from C++ Builder 5 on
>> another machine and my app talks to it and receives from it just fine.
>> AND I can use the Chat example program to talk to the embedded
>> server device and it WILL see the responses from the server.  Both
>> applications use the same TClientSocket component.
>
>
>
> Gambit
>
> 
Re: TClientSocket OnRead event issues
#1934
Author: Remy Lebeau (TeamB)
Date: Thu, 14 Sep 2006 01:22
17 lines
1597 bytes
"Josh Arnold" <jdaudio02@hotmail.com> wrote in message
news:4508aab1$1@newsgroups.borland.com...

> I agree, but the old example chat program works using the
> same TClientSocket component and nearly identical code.

But, you are using it in two different IDE versions.  You also did not
indicate whether the embedded server is behind a router or firewall.  It
could be that the successful application is able to reach the server while
the failing application is being blocked?  It could also just be that your
reading code is wrong and you are causing OnRead notification messages to be
ignored.  It is really hard to say right now without seeing your actual
code.


Gambit
Re: TClientSocket OnRead event issues
#1935
Author: Josh Arnold
Date: Thu, 14 Sep 2006 12:30
72 lines
2931 bytes
Gambit-

Here is my relevant code:

void Tfrm_Main::TCP_Init()
{

 //client socket communicates with embedded server socket
 client = new TClientSocket(frm_Main);
 client->Address = "192.168.78.139";

 client->Port = 1024;
 client->ClientType = ctNonBlocking;
 client->Open();
 client->OnRead = myClientRead;

}

//Send message
void __fastcall Tfrm_Main::Button4Click(TObject *Sender)
{

 client->Socket->SendText("hello\n");


}


//Event handler
void __fastcall Tfrm_Main::myClientRead(System::TObject *Sender,
TCustomWinSocket                 *Socket)
{
    Memo1->Text = Socket->ReceiveText();
   //receiveFlag = true;
}



Its farily simple I call the TCP_Init() function on a button click. Then
send a message on Button4Click event.

The server is set up to immediately reply back to the failing client app,
and as mentioned before, the server is responding.

There is a router in between the two but no firewall. The Chat app works
with the server device from the same machine that fails on the client app.

Thanks for the quick help,
-Josh

"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:4508b143@newsgroups.borland.com...
>
> "Josh Arnold" <jdaudio02@hotmail.com> wrote in message
> news:4508aab1$1@newsgroups.borland.com...
>
> > I agree, but the old example chat program works using the
> > same TClientSocket component and nearly identical code.
>
> But, you are using it in two different IDE versions.  You also did not
> indicate whether the embedded server is behind a router or firewall.  It
> could be that the successful application is able to reach the server while
> the failing application is being blocked?  It could also just be that your
> reading code is wrong and you are causing OnRead notification messages to
be
> ignored.  It is really hard to say right now without seeing your actual
> code.
>
>
> Gambit
>
>
Re: TClientSocket OnRead event issues
#1936
Author: Hans Galema
Date: Thu, 14 Sep 2006 13:31
21 lines
1642 bytes
Josh Arnold wrote:

>  client->Open();
>  client->OnRead = myClientRead;

Assign the eventhandler first:

   client->OnRead = myClientRead;
   client->Open();

What if you assign an onconnecthandler too?

   client->OnConnect = myClientConnect;
   client->OnRead = myClientRead;
   client->Open();

Does that trigger?

You should wait for OnConnect before sending anything.

HAns.
Re: TClientSocket OnRead event issues
#1937
Author: Josh Arnold
Date: Thu, 14 Sep 2006 14:56
30 lines
1860 bytes
Ok, I modified my code per Hans suggestion and still nothing.

The OnConnect event is fired and I can get the RemoteAddress from the
socket, but the responses from the server still do not trigger any OnRead
events.


"Hans Galema" <notused@notused.nl> wrote in message
news:45095b16@newsgroups.borland.com...
> Josh Arnold wrote:
>
> >  client->Open();
> >  client->OnRead = myClientRead;
>
> Assign the eventhandler first:
>
>    client->OnRead = myClientRead;
>    client->Open();
>
> What if you assign an onconnecthandler too?
>
>    client->OnConnect = myClientConnect;
>    client->OnRead = myClientRead;
>    client->Open();
>
> Does that trigger?
>
> You should wait for OnConnect before sending anything.
>
> HAns.
Re: TClientSocket OnRead event issues
#1938
Author: Remy Lebeau (TeamB)
Date: Thu, 14 Sep 2006 17:02
21 lines
1808 bytes
"Josh Arnold" <jarnold@atterotech.com> wrote in message
news:450949ba$1@newsgroups.borland.com...

Why are you waiting until after calling Open() to assign the event handler?
You should be doing it before instead:

    client->OnRead = myClientRead;
    client->Open();

>  client->Socket->SendText("hello\n");

You are not checking the return value to make sure that the full text is
actually being sent.  You are not taking into account that partial text can
be sent, requiring you to re-send the remaining data again.  You are also
not taking into account that if a send operation blocks, the send will
report a failure, and you then have to wait until the OnWrite event is
triggered before you can send any further data.


Gambit
Re: TClientSocket OnRead event issues
#1939
Author: Josh Arnold
Date: Thu, 14 Sep 2006 17:26
46 lines
2384 bytes
Problem solved for now,

It appears that the client socket needs a "garbage read" in order to get the
OnRead event working.
Since the OnConnect event fires I just stuck in a
socket->RecieveText() and now the responses from the server are heard.

Thanks for the help, don't know if this qualifies as a bug or not?

-Josh


"Josh Arnold" <jarnold@atterotech.com> wrote in message
news:45096c00@newsgroups.borland.com...
> Ok, I modified my code per Hans suggestion and still nothing.
>
> The OnConnect event is fired and I can get the RemoteAddress from the
> socket, but the responses from the server still do not trigger any OnRead
> events.
>
>
> "Hans Galema" <notused@notused.nl> wrote in message
> news:45095b16@newsgroups.borland.com...
> > Josh Arnold wrote:
> >
> > >  client->Open();
> > >  client->OnRead = myClientRead;
> >
> > Assign the eventhandler first:
> >
> >    client->OnRead = myClientRead;
> >    client->Open();
> >
> > What if you assign an onconnecthandler too?
> >
> >    client->OnConnect = myClientConnect;
> >    client->OnRead = myClientRead;
> >    client->Open();
> >
> > Does that trigger?
> >
> > You should wait for OnConnect before sending anything.
> >
> > HAns.
>
>
Re: TClientSocket OnRead event issues
#1940
Author: Remy Lebeau (TeamB)
Date: Thu, 14 Sep 2006 17:30
14 lines
1605 bytes
"Josh Arnold" <jarnold@atterotech.com> wrote in message
news:45098f13@newsgroups.borland.com...

> It appears that the client socket needs a "garbage read"
> in order to get the OnRead event working.

No, it does not.  Like I said earlier, non-blocking sockets use window
messages as internal notifications.  You do not need a dummy read in order
to begin receiving those notifications.  Something else has to be happening
that is blocking them.


Gambit
Re: TClientSocket OnRead event issues
#1941
Author: Josh Arnold
Date: Thu, 14 Sep 2006 21:50
39 lines
2358 bytes
Ok,

I still don't see what is blocking the initial read but it seems to be
working now.

My new problem is that I need to send a lot of small messages and get them
back ideally in the order that they were sent.

What would be the best approach to this problem?



"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:45098bd2$1@newsgroups.borland.com...
>
> "Josh Arnold" <jarnold@atterotech.com> wrote in message
> news:450949ba$1@newsgroups.borland.com...
>
> Why are you waiting until after calling Open() to assign the event
handler?
> You should be doing it before instead:
>
>     client->OnRead = myClientRead;
>     client->Open();
>
> >  client->Socket->SendText("hello\n");
>
> You are not checking the return value to make sure that the full text is
> actually being sent.  You are not taking into account that partial text
can
> be sent, requiring you to re-send the remaining data again.  You are also
> not taking into account that if a send operation blocks, the send will
> report a failure, and you then have to wait until the OnWrite event is
> triggered before you can send any further data.
>
>
> Gambit
>
>
Re: TClientSocket OnRead event issues
#1942
Author: Remy Lebeau (TeamB)
Date: Thu, 14 Sep 2006 22:03
18 lines
1699 bytes
"Josh Arnold" <jarnold@atterotech.com> wrote in message
news:4509ccfc$1@newsgroups.borland.com...

> My new problem is that I need to send a lot of small messages
> and get them back ideally in the order that they were sent.

TCP/IP guarantees that for you.  All you have to is read whatever you
receive.  They will already be in the proper order.

> What would be the best approach to this problem?

Please go to http://www.deja.com and search through the newsgroup archives.
Effectively usage of TClientSocket (especially in non-blocking mode) has
been discussed many many times before, with full code examples.


Gambit
Re: TClientSocket OnRead event issues
#1889
Author: Arnoud
Date: Mon, 25 Sep 2006 12:27
40 lines
2380 bytes
Hi,

I made a similar program with BCB5 connecting to a embedded server
running windows CE. The application has several TClientSocket components
on the form. To communicate with the embedded device I make the
TClientSocket connect and wait for the device to send its identification
data before sending any data to it.

Some of the established connections never trigger any OnRead event,
making the BCB application believe that the device was successfully
connected, but never responded with any data (no matter how many data
the embedded device sends). In this situation sending data to the
embedded device (using SendBuf) works Ok and the winCE application
received the command.

I started to log the TCP traffic and i noticed that the SYN/SYNACK/ACK
handshake appeared to be normal, I could also see the incomming data
from the embedded device.

1.) SYN packet     app->device
2.) SYN ACK packet device->app
3.) ACK packet     app->device
4.) DATA packet    device->app

I logged the following events of a connection that does not trigger any
OnRead event:

1.) OnConnecting()
2.) OnRead() - returning 0 bytes
3.) OnConnect()
4.) Nothing..

Luckilly 95% of all connections work normally. I added a timeout, making
the same TClientSocket component Close and then Connect to the same
device. The retry works fine (mostly)

I have little idea why it happens, anyone have an idea?

Thank you,
-Arnoud
Re: TClientSocket OnRead event issues
#1903
Author: Arnoud
Date: Tue, 26 Sep 2006 13:57
28 lines
2199 bytes
Josh Arnold schreef:
> Problem solved for now,
> 
> It appears that the client socket needs a "garbage read" in order to get the
> OnRead event working.
> Since the OnConnect event fires I just stuck in a
> socket->RecieveText() and now the responses from the server are heard.
> 
> Thanks for the help, don't know if this qualifies as a bug or not?
> 
> -Josh

Hi Josh,

I got a similar problem in my communications with a embedded tcp/ip 
stack, i addded your 'garbage read' idea and it worked for me as well.

OnRead() seems to trigger only *once*, and then expect our applications 
to do at least one Read operation to trigger again. Our applications 
probably did not expect to read data before OnConnect. The 'garbage 
read' probably reset the flag so OnRead() fired again.

Did you use any other components inside your application?
I have used a NMUDP(fastnet) component to handle someUDP traffic.

Thank you for sharing the idea!

-Arnoud
Re: TClientSocket OnRead event issues
#1904
Author: Remy Lebeau (TeamB)
Date: Tue, 26 Sep 2006 16:56
58 lines
3830 bytes
"Arnoud" <vult-r@endless-online.com> wrote in message
news:4519327b@newsgroups.borland.com...

> OnRead() seems to trigger only *once*, and then expect our
> applications to do at least one Read operation to trigger again.

That is how non-blocking sockets are designed to work.  The socket only
sends one OnRead event to let you know that data is available, and then your
application has to read what is available before a new OnRead event can be
triggered again.  This is explained in the socket API documentation:

    (begin quote)

    The Windows Sockets DLL will not continually flood an application with
messages for a particular network event. Having successfully posted
notification of a particular event to an application window, no further
message(s) for that network event will be posted to the application window
until the application makes the function call which implicitly re-enables
notification of that network event.

    Event            Re-enabling function
    FD_READ    recv, recvfrom, WSARecv, or WSARecvFrom
    ...

    Any call to the re-enabling routine, even one which fails, results in
re-enabling of message posting for the relevant event.

    For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is
"level-triggered." This means that if the re-enabling routine is called and
the relevant condition is still met after the call, a WSAAsyncSelect message
is posted to the application. This allows an application to be event-driven
and not be concerned with the amount of data that arrives at any one time.
Consider the following sequence:

    1. Network transport stack receives 100 bytes of data on socket s and
causes Windows Sockets 2 to post an FD_READ message.
    2. The application issues recv(s, buffptr, 50, 0) to read 50 bytes.
    3. Another FD_READ message is posted since there is still data to be
read.

    With these semantics, an application need not read all available data in
response to an FD_READ message - a single recv in response to each FD_READ
message is appropriate. If an application issues multiple recv calls in
response to a single FD_READ, it can receive multiple FD_READ messages. Such
an application may need to disable FD_READ messages before starting the recv
calls by calling WSAAsyncSelect with the FD_READ event not set.

    (end quote)

You DO NOT, however, need to do a "garbage" read to get the OnRead event to
trigger in the first place.  If you connect to a server and do not do any
reads at all, you will still get an OnRead event when the server sends data.
I have been using TClientSocket for years and never had any problems with
that.


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads