🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
29 messages
29 total messages Started by Eric Patterson Mon, 17 Apr 2006 13:47
TServerSocket SendText Exception
#2465
Author: Eric Patterson
Date: Mon, 17 Apr 2006 13:47
18 lines
1694 bytes
I am having this akward exception being thrown randomly by the SendText 
method in a TServerSocket component.  I check to make sure there is an 
active connection right before I do a SendText and pass it an ansistring. 
The exception is being thrown at random times usually after running more 
then 6 hours.  The exception that is being thrown is an invalid integer 
exception.  Then right after that one, the same line throws an eaccess 
violation.  As anyone seen this problem before or know what is wrong.  Here 
is my code snippet:

while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AMsg+"\n"))==-1)
          {
            Sleep(10);       // allow some time for Socket to send the 
queued up data.
          }

I am using BCD 5.  Thanks.

Eric
Re: TServerSocket SendText Exception
#2467
Author: Remy Lebeau (TeamB)
Date: Mon, 17 Apr 2006 17:02
25 lines
1979 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:44439c71$1@newsgroups.borland.com...

> I check to make sure there is an active connection right before I do
> a SendText and pass it an ansistring.

Your code is not using SendText() correctly in general.  You are not taking
into account that SendText() may not send all of your data in a single
operation, requiring you to re-call SendText() multiple times in a loop in
order to send all of your string.  Please go to http://www.deja.com and
search through the newsgroup archives.  Sample code has been posted many
times before.

 The exception is being thrown at random times usually after running more
> then 6 hours.  The exception that is being thrown is an invalid integer
> exception.

Do you mean that you are getting an EListError exception with a message of
"List index out of bounds (12345)" ?  If so, then the only way that
particular exception can occur in the code you showed is if you are passing
an incorrect index value to the Connections[] property.


Gambit
Re: TServerSocket SendText Exception
#2470
Author: Eric Patterson
Date: Mon, 17 Apr 2006 18:07
43 lines
2843 bytes
Thanks for the insight.  I understand what you mean but can't find an 
example on the newsgroup to help.  So I should continue to call SentText 
until it returns a value of ???.  I would think zero but it does state that 
the return value can be less then zero also.  What values less then zero can 
be returned and what do they mean?  Should an OnError event be written since 
I will continue to SendText until it goes through?  Since I am writing the 
same message to multiple connected clients can I use the OnClientWrite event 
somehow?  Thanks.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4443ca2a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44439c71$1@newsgroups.borland.com...
>
>> I check to make sure there is an active connection right before I do
>> a SendText and pass it an ansistring.
>
> Your code is not using SendText() correctly in general.  You are not 
> taking
> into account that SendText() may not send all of your data in a single
> operation, requiring you to re-call SendText() multiple times in a loop in
> order to send all of your string.  Please go to http://www.deja.com and
> search through the newsgroup archives.  Sample code has been posted many
> times before.
>
> The exception is being thrown at random times usually after running more
>> then 6 hours.  The exception that is being thrown is an invalid integer
>> exception.
>
> Do you mean that you are getting an EListError exception with a message of
> "List index out of bounds (12345)" ?  If so, then the only way that
> particular exception can occur in the code you showed is if you are 
> passing
> an incorrect index value to the Connections[] property.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2471
Author: Eric Patterson
Date: Mon, 17 Apr 2006 18:24
54 lines
2926 bytes
After thinking a minute, what about this:

          int len = AMsg.Length();
          while(len > 0)
          {
                len -= 
Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AMsg+"\n"))
                if( len != 0)
                {
                     Sleep(10);       // allow some time for Socket to send 
the queued up data.
                }
          }


That way it will continue to send until no more length is detected.  The 
only thing I don't like is that when it returns a negative value I won't do 
anything but add to my length (which is probably wrong) but I figure if a 
negative is returned then the OnError event should catch it.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4443ca2a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44439c71$1@newsgroups.borland.com...
>
>> I check to make sure there is an active connection right before I do
>> a SendText and pass it an ansistring.
>
> Your code is not using SendText() correctly in general.  You are not 
> taking
> into account that SendText() may not send all of your data in a single
> operation, requiring you to re-call SendText() multiple times in a loop in
> order to send all of your string.  Please go to http://www.deja.com and
> search through the newsgroup archives.  Sample code has been posted many
> times before.
>
> The exception is being thrown at random times usually after running more
>> then 6 hours.  The exception that is being thrown is an invalid integer
>> exception.
>
> Do you mean that you are getting an EListError exception with a message of
> "List index out of bounds (12345)" ?  If so, then the only way that
> particular exception can occur in the code you showed is if you are 
> passing
> an incorrect index value to the Connections[] property.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2472
Author: Eric Patterson
Date: Mon, 17 Apr 2006 18:40
63 lines
2964 bytes
What about this:

          int len = AMsg.Length();
          while(len > 0)
          {
            int sendReturn = 
Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AMsg+"\n"));
            if(sendReturn == -1)
            {
                //need to wait for OnClientWrite
                while( OnClientWriteBool != true )
                {
                        Sleep(10);
                }
                OnClientWriteBool = false;
            }else
            {
                len -= sendReturn;
            }
            if( len != 0)
            {
               Sleep(10);       // allow some time for Socket to send the 
queued up data.
            }
          }

The OnClientWriteBool is turned 'true' by the OnClientWrite event.

Eric



"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4443ca2a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44439c71$1@newsgroups.borland.com...
>
>> I check to make sure there is an active connection right before I do
>> a SendText and pass it an ansistring.
>
> Your code is not using SendText() correctly in general.  You are not 
> taking
> into account that SendText() may not send all of your data in a single
> operation, requiring you to re-call SendText() multiple times in a loop in
> order to send all of your string.  Please go to http://www.deja.com and
> search through the newsgroup archives.  Sample code has been posted many
> times before.
>
> The exception is being thrown at random times usually after running more
>> then 6 hours.  The exception that is being thrown is an invalid integer
>> exception.
>
> Do you mean that you are getting an EListError exception with a message of
> "List index out of bounds (12345)" ?  If so, then the only way that
> particular exception can occur in the code you showed is if you are 
> passing
> an incorrect index value to the Connections[] property.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2473
Author: Remy Lebeau (TeamB)
Date: Mon, 17 Apr 2006 21:10
56 lines
3188 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4443d955$1@newsgroups.borland.com...

> I understand what you mean but can't find an example on the newsgroup to
help.

Did you do a search for SendText?  Did you search for SendBuf()?  I know
that code examples exist in the archives on this topic.

SendText() calls SendBuf() internally.  Since SendText() does not allow you
specify an index into the string, it is generally more efficient to call
SendBuf() directly and not use SendText() at all.

> So I should continue to call SentText until it returns a value of ???.

That is not the way to handle it.  If you want to send 50 characters, and
SendText() only accepts 10, you have to remove the first 10 from the string
and then call SendText() again pass in only the remaining 40 characters,
repeating as needed until all 50 characters have been sent.

> I would think zero

No.  A return value of zero means that the socket was disconnected by the
other party.

> but it does state that the return value can be less then zero also.

That means that a socket error occured.  You have to use WSAGetLastError()
to find out which error occured.  The only error you can safely ignore is
WSAEWOULDBLOCK.

> What values less then zero can be returned

-1 is the only one.  It is the same value as SOCKET_ERROR, as SendText()
(and SendBuf()) simply returns whatever value the socket API send() function
returns.

> Should an OnError event be written since I will continue to SendText until
it goes through?

If an error other than WSAEWOULDBLOCK occurs, SendText() will throw an
exception, unless the OnError event handler prevents it.

> Since I am writing the same message to multiple connected clients can
> I use the OnClientWrite event somehow?

The only time the OnWrite event is triggered is when a socket becomes
writable after a blocking send occured on a non-blocking socket.  When
send() returns SOCKET_ERROR and WSAGetLastError() then returns
WSAEWOULDBLOCK, nothing can be sent to that socket until the OnWrite event
occurs.  Any attempt to send data before that time will just produce more
WSAEWOULDBLOCK errors.


Gambit
Re: TServerSocket SendText Exception
#2474
Author: Remy Lebeau (TeamB)
Date: Mon, 17 Apr 2006 21:18
74 lines
2858 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4443dd4e@newsgroups.borland.com...

> After thinking a minute, what about this:
<snip>
> That way it will continue to send until no more length is detected.

No, because you are re-sending the entire string contents every time, even
for portions of it that are successfully sent in previous loop iterations.
Youare not adjusting the sending to send only the characters that are
actually pending.

A more accurate approach is as follows:

    TCustomWinSocket *Socket =
Server->ServerSocket1->Socket->Connections[ii];
    AnsiString temp = AMsg + "\n";
    int len;

    while( temp.Length() > 0 )
    {
        len = Socket->SendText(temp);
        if( len > 0 )
        {
            temp = temp.SubString(len+1, MaxInt);
            continue;
        }

        if( (len == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
        {
            Sleep(10);
            continue;
        }

        break;
    }

Alternatively:

    TCustomWinSocket *Socket =
Server->ServerSocket1->Socket->Connections[ii];
    AnsiString temp = AMsg + "\n";
    int sent, len = temp.Length();
    char *ptr = temp.c_str();

    while( len > 0 )
    {
        sent = Socket->SendBuf(ptr, len);
        if( sent > 0 )
        {
            ptr += sent;
            len -= sent;
            continue;
        }

        if( (sent == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
        {
            Sleep(10);
            continue;
        }

        break;
    }


> I figure if a negative is returned then the OnError event should catch it.

SendText/Buf() will still return the negative value regardless of whether
the OnError event is used.  All the OnError event can do is choose whether
to stop the error from throwing an exception or not.


Gambit
Re: TServerSocket SendText Exception
#2475
Author: Remy Lebeau (TeamB)
Date: Mon, 17 Apr 2006 21:21
17 lines
1671 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4443e13c$1@newsgroups.borland.com...

> What about this:

You are still not checking the reason why -1 is being returned.  The only
condition that is valid for the OnWrite event to be triggered is when
WSAGetLastError() returns WSAEWOULDBLOCK.  You are also not taking into
account that non-blocking sockets require window messages to be processed in
order for the OnWrite event to be triggered at all, so your code is going to
deadlock indefinately since you do not process pending messages at all.  And
you are still not adjusting the writing to not send characters that have
already been sent.


Gambit
Re: TServerSocket SendText Exception
#2378
Author: Eric Patterson
Date: Wed, 19 Apr 2006 12:19
36 lines
2254 bytes
Thank you for all your help.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4443ca2a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44439c71$1@newsgroups.borland.com...
>
>> I check to make sure there is an active connection right before I do
>> a SendText and pass it an ansistring.
>
> Your code is not using SendText() correctly in general.  You are not 
> taking
> into account that SendText() may not send all of your data in a single
> operation, requiring you to re-call SendText() multiple times in a loop in
> order to send all of your string.  Please go to http://www.deja.com and
> search through the newsgroup archives.  Sample code has been posted many
> times before.
>
> The exception is being thrown at random times usually after running more
>> then 6 hours.  The exception that is being thrown is an invalid integer
>> exception.
>
> Do you mean that you are getting an EListError exception with a message of
> "List index out of bounds (12345)" ?  If so, then the only way that
> particular exception can occur in the code you showed is if you are 
> passing
> an incorrect index value to the Connections[] property.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2379
Author: Eric Patterson
Date: Thu, 20 Apr 2006 15:21
63 lines
3386 bytes
Mr. Gambit

I believe I understand how the ServerSocket should be used.  I have though 
had this setup working flawlessly until I moved to windows xp; I was running 
on nt which makes me reluctent to change my code drastically.  I did finally 
get a good stack call trace of the exception that is being thrown and it is 
an invalid pointer exception and the stack looks like this:

Module                Unit                   Method        Line
-----------------------------------------------------
VCL50.BPL        System.pas        _FreeMem

VCL50.BPL        System.pas        _LStrClr

VmeServer.exe    MsgServer.cpp  Execute        56


The starting point of the exception is coming from this line (line 56 in 
MsgServer.cpp):

while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AMsg+"\n"))==-1)


I also did some digging into onError errorCodes that the serverSocket can be 
throwing and I found at no time does my application go into the onError 
function.  So I am hoping you have some insight into this invalid pointer 
exception coming from SendText.  Thanks again

Eric



"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4443ca2a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44439c71$1@newsgroups.borland.com...
>
>> I check to make sure there is an active connection right before I do
>> a SendText and pass it an ansistring.
>
> Your code is not using SendText() correctly in general.  You are not 
> taking
> into account that SendText() may not send all of your data in a single
> operation, requiring you to re-call SendText() multiple times in a loop in
> order to send all of your string.  Please go to http://www.deja.com and
> search through the newsgroup archives.  Sample code has been posted many
> times before.
>
> The exception is being thrown at random times usually after running more
>> then 6 hours.  The exception that is being thrown is an invalid integer
>> exception.
>
> Do you mean that you are getting an EListError exception with a message of
> "List index out of bounds (12345)" ?  If so, then the only way that
> particular exception can occur in the code you showed is if you are 
> passing
> an incorrect index value to the Connections[] property.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2380
Author: Remy Lebeau (TeamB)
Date: Thu, 20 Apr 2006 16:33
22 lines
1655 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4447a6f6$1@newsgroups.borland.com...

> I believe I understand how the ServerSocket should be used.

Apparently you don't, because you didn't pay attention to a word I've told
you.  Your code is still wrong.  You are not even close to using the kind of
code I gave you earlier.  Did you even try it?

> The starting point of the exception is coming from this line
> (line 56 in MsgServer.cpp):
>
>
while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AM
sg+"\n"))==-1)

As I explained to you earlier, that is a very bad way to send text to a
socket.


Gambit
Re: TServerSocket SendText Exception
#2381
Author: Eric Patterson
Date: Thu, 20 Apr 2006 17:11
37 lines
2344 bytes
That is all fine but why?  I would love to fix my issue but I am not a 
person to shoot shotguns in the dark and hope to hit the target.  If what 
you have gave me before will fix it then someone here should be able to tell 
me why that will fix it.  What causes the invalid pointer exception?  Why 
did this work in NT and now it doesn't in XP?  Please tell me the reason why 
I have this problem instead of telling me your way will fix it.  Thanks.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:4447b917$3@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:4447a6f6$1@newsgroups.borland.com...
>
>> I believe I understand how the ServerSocket should be used.
>
> Apparently you don't, because you didn't pay attention to a word I've told
> you.  Your code is still wrong.  You are not even close to using the kind 
> of
> code I gave you earlier.  Did you even try it?
>
>> The starting point of the exception is coming from this line
>> (line 56 in MsgServer.cpp):
>>
>>
> while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AM
> sg+"\n"))==-1)
>
> As I explained to you earlier, that is a very bad way to send text to a
> socket.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2382
Author: Bob Gonder
Date: Thu, 20 Apr 2006 18:36
23 lines
2255 bytes
Eric Patterson wrote:

>That is all fine but why?  I would love to fix my issue but I am not a 
>person to shoot shotguns in the dark and hope to hit the target.  If what 
>you have gave me before will fix it then someone here should be able to tell 
>me why that will fix it.  What causes the invalid pointer exception?  Why 
>did this work in NT and now it doesn't in XP?  Please tell me the reason why 
>I have this problem instead of telling me your way will fix it.  Thanks.

Remy explained the "why" in the same message where he explained the
"correct" way to do it.
In short:
	If SendText() fails to send the entire amount (due to a slow
network perhaps, or a smaller packet size on the XP machine), then you
are resending the entire string again, and again, and again...

>> while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AM
>> sg+"\n"))==-1)

In addition to that, you are creating and destroying a temporary
AnsiString each time, which may or may not be a further problem (but,
if you follow Remy's solution, this particular "problem" would also go
away.)
Re: TServerSocket SendText Exception
#2383
Author: Eric Patterson
Date: Thu, 20 Apr 2006 18:53
41 lines
2931 bytes
Thank you.  I did do the change and I am getting different problems now 
which I am trying to fix but if SendText doesn't send the entire amount and 
I fill the socket buffer wouldn't it call the ServerSocket OnError event? 
My network is a 10/100 hub which is sitting right on top of the computer and 
another computer sitting next to it (they are the only two items on the hub) 
so I don't think speed is an issue.  Did XP shrink it default packet size 
versus what they had on NT?  Thanks again.

Eric


"Bob Gonder" <notbg@notmindspring.invalid> wrote in message 
news:4mkf429644ao82ak653gcltqtf4v2g698j@4ax.com...
> Eric Patterson wrote:
>
>>That is all fine but why?  I would love to fix my issue but I am not a
>>person to shoot shotguns in the dark and hope to hit the target.  If what
>>you have gave me before will fix it then someone here should be able to 
>>tell
>>me why that will fix it.  What causes the invalid pointer exception?  Why
>>did this work in NT and now it doesn't in XP?  Please tell me the reason 
>>why
>>I have this problem instead of telling me your way will fix it.  Thanks.
>
> Remy explained the "why" in the same message where he explained the
> "correct" way to do it.
> In short:
> If SendText() fails to send the entire amount (due to a slow
> network perhaps, or a smaller packet size on the XP machine), then you
> are resending the entire string again, and again, and again...
>
>>> while(Server->ServerSocket1->Socket->Connections[ii]->SendText(AnsiString(AM
>>> sg+"\n"))==-1)
>
> In addition to that, you are creating and destroying a temporary
> AnsiString each time, which may or may not be a further problem (but,
> if you follow Remy's solution, this particular "problem" would also go
> away.)
>
>
> 
Re: TServerSocket SendText Exception
#2386
Author: Remy Lebeau (TeamB)
Date: Thu, 20 Apr 2006 22:23
15 lines
1393 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4447c0b0$1@newsgroups.borland.com...

> That is all fine but why?

I already gave you a detailed explanation about that.  Please go re-read my
earlier reply more closely.

> I would love to fix my issue

Then please try the code I already gave you.


Gambit
Re: TServerSocket SendText Exception
#2385
Author: Remy Lebeau (TeamB)
Date: Thu, 20 Apr 2006 22:24
11 lines
1439 bytes
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message
news:4mkf429644ao82ak653gcltqtf4v2g698j@4ax.com...

> In addition to that, you are creating and destroying a temporary
> AnsiString each time, which may or may not be a further problem

That is not a problem - other than the extra memory allocations required.


Gambit
Re: TServerSocket SendText Exception
#2387
Author: Remy Lebeau (TeamB)
Date: Thu, 20 Apr 2006 22:26
18 lines
1691 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4447d8b4$1@newsgroups.borland.com...

> I did do the change and I am getting different problems now
> which I am trying to fix

What problems are you having now?  Please elaborate.

> if SendText doesn't send the entire amount and I fill the socket buffer
> wouldn't it call the ServerSocket OnError event?

No.  The OnError event is only triggered for actual socket errors.  A
blocking send is not an error.  WSAEWOULDBLOCK will never trigger the
OnError event.


Gambit
Re: TServerSocket SendText Exception
#2390
Author: Eric Patterson
Date: Fri, 21 Apr 2006 11:47
41 lines
2812 bytes
Gambit

The problem I was having was a software exception (0x0eedfade) occured in 
the application at the location 0x7c81e633.  I found after some research 
that this usually shows up when a linked dll has an excpetion which isn't 
being handled.  I removed a dll which I was temporary using to track memory 
sector overwrites; since I have never seen that error until now.  That 
exception has gone away and since in this process of finding my problems I 
removed clearing the errorcode integer on a Socket OnError event, I came in 
this morning with an asynchronous socket error 10053 which I already know is 
what the socket throws back to me when it is full and busy.  I would of 
expected this error soon after starting the app but it didn't occur until 5 
hours later.  I will make the additions now that when I see a 10053 in the 
OnError event to wait for a ClientWrite Event to occur before continuing on; 
like we have discussed before.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:44480b3f$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:4447d8b4$1@newsgroups.borland.com...
>
>> I did do the change and I am getting different problems now
>> which I am trying to fix
>
> What problems are you having now?  Please elaborate.
>
>> if SendText doesn't send the entire amount and I fill the socket buffer
>> wouldn't it call the ServerSocket OnError event?
>
> No.  The OnError event is only triggered for actual socket errors.  A
> blocking send is not an error.  WSAEWOULDBLOCK will never trigger the
> OnError event.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2391
Author: Remy Lebeau (TeamB)
Date: Fri, 21 Apr 2006 16:42
38 lines
2976 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:4448c637$1@newsgroups.borland.com...

> That exception has gone away and since in this process of finding
. my problems I removed clearing the errorcode integer on a Socket
> OnError event, I came in this morning with an asynchronous socket
> error 10053 which I already know is what the socket throws back
> to me when it is full and busy.

10053 is an abnormal disconnect.  The socket forced itself to disconnect due
to an internal error.  That can happen for a number of reasons.  Being "full
and busy" is not likely to be the cause.  If the socket's internal buffer
were simply full and couldn't accept more data yet, you would either get
WSAENOBUFS as the ErrorCode in the OnError event, or you would not get the
OnError event at all if WSAGetLastError() returns WSAEWOULDBLOCK, which the
VCL handles internally.

> I would of expected this error soon after starting the app but it
> didn't occur until 5 hours later.

If you were filling up the socket's internal buffer after several hours,
then that suggests to me that you are trying to send data faster than the
socket can send it out, and the buffer slowly fills up over time. As I
explained to you earler, if the socket reports WSAEWOULDBLOCK on a sent
operation, then you *must* wait for the OnWrite event to be triggered before
you can send more data.  If your application needs to send data before that
happens, then you will just have to queue the data for later.

> I will make the additions now that when I see a 10053 in the OnError
> event to wait for a ClientWrite Event to occur before continuing on;
> like we have discussed before.

That is the wrong use of the OnWrite event.  10053 is a fatal error.  The
connection is gone.  You have to reconect.


Gambit
Re: TServerSocket SendText Exception
#2392
Author: Eric Patterson
Date: Fri, 21 Apr 2006 16:52
59 lines
2813 bytes
I seem to still have an invalid pointer.  I was using this snippet:

TCustomWinSocket *Socket =
Server->ServerSocket1->Socket->Connections[ii];
    AnsiString temp = AMsg + "\n";
    int len;

    while( temp.Length() > 0 )
    {
        len = Socket->SendText(temp);
        if( len > 0 )
        {
-->       temp = temp.SubString(len+1, MaxInt);
            continue;
        }

        if( (len == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
        {
            Sleep(10);
            continue;
        }

        break;
    }

The exception occured on the line using SubString function (denoted with an 
arrorw).  I looked at the details of the SubString method and in this case 
it will return a substring starting at len+1 and go all the way to MaxInt. 
I am going to attempt using the sendbuf example that you provided since that 
makes more sense and I can control the bounds of the pointers.  I do have a 
question regarding AnsiStrings now though: when using an equal operator is 
that doing a copy from one memory location to another or is that just 
creating another pointer to point to the same location AMsg is sitting? 
Maybe my AMsg array is being taken way before sendbuf (or sendtext) is done 
with it.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:44480aa5$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:4447c0b0$1@newsgroups.borland.com...
>
>> That is all fine but why?
>
> I already gave you a detailed explanation about that.  Please go re-read 
> my
> earlier reply more closely.
>
>> I would love to fix my issue
>
> Then please try the code I already gave you.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2393
Author: Eric Patterson
Date: Fri, 21 Apr 2006 16:54
52 lines
3296 bytes
That makes a ton of sense.  I will fix.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:44490c3a$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:4448c637$1@newsgroups.borland.com...
>
>> That exception has gone away and since in this process of finding
> . my problems I removed clearing the errorcode integer on a Socket
>> OnError event, I came in this morning with an asynchronous socket
>> error 10053 which I already know is what the socket throws back
>> to me when it is full and busy.
>
> 10053 is an abnormal disconnect.  The socket forced itself to disconnect 
> due
> to an internal error.  That can happen for a number of reasons.  Being 
> "full
> and busy" is not likely to be the cause.  If the socket's internal buffer
> were simply full and couldn't accept more data yet, you would either get
> WSAENOBUFS as the ErrorCode in the OnError event, or you would not get the
> OnError event at all if WSAGetLastError() returns WSAEWOULDBLOCK, which 
> the
> VCL handles internally.
>
>> I would of expected this error soon after starting the app but it
>> didn't occur until 5 hours later.
>
> If you were filling up the socket's internal buffer after several hours,
> then that suggests to me that you are trying to send data faster than the
> socket can send it out, and the buffer slowly fills up over time. As I
> explained to you earler, if the socket reports WSAEWOULDBLOCK on a sent
> operation, then you *must* wait for the OnWrite event to be triggered 
> before
> you can send more data.  If your application needs to send data before 
> that
> happens, then you will just have to queue the data for later.
>
>> I will make the additions now that when I see a 10053 in the OnError
>> event to wait for a ClientWrite Event to occur before continuing on;
>> like we have discussed before.
>
> That is the wrong use of the OnWrite event.  10053 is a fatal error.  The
> connection is gone.  You have to reconect.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2394
Author: Eric Patterson
Date: Fri, 21 Apr 2006 16:55
68 lines
3167 bytes
Forget this for a minute because I need to fix the issue with not waiting 
for CleintWrite event after a WSAEWOULDBLOCK

Eric

"Eric Patterson" <eric.patterson@bepco.com> wrote in message 
news:44490de6$1@newsgroups.borland.com...
>I seem to still have an invalid pointer.  I was using this snippet:
>
> TCustomWinSocket *Socket =
> Server->ServerSocket1->Socket->Connections[ii];
>    AnsiString temp = AMsg + "\n";
>    int len;
>
>    while( temp.Length() > 0 )
>    {
>        len = Socket->SendText(temp);
>        if( len > 0 )
>        {
> -->       temp = temp.SubString(len+1, MaxInt);
>            continue;
>        }
>
>        if( (len == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
>        {
>            Sleep(10);
>            continue;
>        }
>
>        break;
>    }
>
> The exception occured on the line using SubString function (denoted with 
> an arrorw).  I looked at the details of the SubString method and in this 
> case it will return a substring starting at len+1 and go all the way to 
> MaxInt. I am going to attempt using the sendbuf example that you provided 
> since that makes more sense and I can control the bounds of the pointers. 
> I do have a question regarding AnsiStrings now though: when using an equal 
> operator is that doing a copy from one memory location to another or is 
> that just creating another pointer to point to the same location AMsg is 
> sitting? Maybe my AMsg array is being taken way before sendbuf (or 
> sendtext) is done with it.
>
> Eric
>
>
> "Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
> news:44480aa5$1@newsgroups.borland.com...
>>
>> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
>> news:4447c0b0$1@newsgroups.borland.com...
>>
>>> That is all fine but why?
>>
>> I already gave you a detailed explanation about that.  Please go re-read 
>> my
>> earlier reply more closely.
>>
>>> I would love to fix my issue
>>
>> Then please try the code I already gave you.
>>
>>
>> Gambit
>>
>>
>
> 
Re: TServerSocket SendText Exception
#2395
Author: Eric Patterson
Date: Fri, 21 Apr 2006 17:46
61 lines
2799 bytes
I just don't get this stuff.  I am still getting an invalid pointer 
exception.  Here is the current snippet:

for(ii=0;ii<Server->ServerSocket1->Socket->ActiveConnections;ii++)
      {
        TCustomWinSocket *Socket = 
Server->ServerSocket1->Socket->Connections[ii];
        AnsiString temp = AMsg + "\n";
        int sent, len = temp.Length();
        char *ptr = temp.c_str();

        while( len > 0 )
        {
                sent = Socket->SendBuf(ptr, len);
                if( sent > 0 )
                {
                        ptr += sent;
                        len -= sent;
                        continue;
                }
                if( (sent == -1) && (WSAGetLastError() == WSAEWOULDBLOCK) )
                {
                        Server->WaitForClientWriteEvent = true;
                        while( Server->WaitForClientWriteEvent )
                        {
                                Sleep(10);
                        }
                        continue;
                }

                break;
        }

     }

You can see I added in the part to wait until a ClientWriteEvent occured 
when a WSAEWOULDBLOCK occurs.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:44480aa5$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:4447c0b0$1@newsgroups.borland.com...
>
>> That is all fine but why?
>
> I already gave you a detailed explanation about that.  Please go re-read 
> my
> earlier reply more closely.
>
>> I would love to fix my issue
>
> Then please try the code I already gave you.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2396
Author: Remy Lebeau (TeamB)
Date: Fri, 21 Apr 2006 19:32
41 lines
3061 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:44490de6$1@newsgroups.borland.com...

> The exception occured on the line using SubString function (denoted
> with an arrorw).  I looked at the details of the SubString method and
> in this case it will return a substring starting at len+1 and go all the
way to MaxInt.

Using MaxInt does not tell SubString() to return a new string that is MaxInt
in length.  The count parameter is truncated to the minimum value between
the specified value and the source string's actual length before the new
string is then allocated.  Using MaxInt is a common way to tell SubString()
to return everything that is remaining in the source string after the
specified position.  But, if it concerns you, you can calculate the
remaining length manually:

    temp = temp.SubString(len+1, temp.Length()-len);

> when using an equal operator is that doing a copy from one memory
> location to another or is that just creating another pointer to point to
> the same location AMsg is sitting?

The latter.  AnsiString is reference-counted.  When one AnsiString is
assigned to another, they share the same memory for the character data, and
a reference count within that memory is incremented.  When an AnsiString is
freed or modified, the reference count on the existing memory is
decremented.  AnsiString copies the characters to a new memory block only
when the string is being modified.

> Maybe my AMsg array is being taken way before sendbuf (or sendtext)
> is done with it.

Nope.  SendText/Buf() copies the specified data into the socket's internal
buffer.  What happens to your data when the call exits is irrelevant.
Besides, you are appending a '\n' character to the end of the AMsg data, so
it doesn't matter what happens to AMsg because your sending is working with
a local AnsiString that has its own memory separate from AMsg.


Gambit
Re: TServerSocket SendText Exception
#2397
Author: Remy Lebeau (TeamB)
Date: Fri, 21 Apr 2006 19:36
18 lines
1772 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:44491a72$1@newsgroups.borland.com...

>                         Server->WaitForClientWriteEvent = true;
>                         while( Server->WaitForClientWriteEvent )
>                         {
>                                 Sleep(10);
>                         }

That will not work.  Non-blocking sockets use window messages internally.
You must pump the message queue in order for those events to occur.  Which
then complicates your code because now clients can connect/disconnect while
you are still looping through them, so your loop can become screwed up
because your code is currently not set up to handle that situation.


Gambit
Re: TServerSocket SendText Exception
#2399
Author: Eric Patterson
Date: Mon, 24 Apr 2006 13:20
40 lines
3051 bytes
Do you think that the Invalid Pointer Exception is coming from the client 
not being present?  The system I have setup should always have a client 
present; I typically (and my test rig is setup this way) only have two 
client's connected to the server application.  They both get the same 
messages no matter what and they should never leave (or disconnect from the 
server).  I can go through and make the server app more robust with the last 
suggestions but I know that I am getting an invalid pointer exception 
dealing with a SendText and the client didn't disconnect.  Also you stated 
earlier that I can't keep doing a sendtext until I get a ClientWrite Event 
after a -1 was returned from a SendText.  Now you are saying I have to do a 
SendText (pump the message queue) so I know the state of the socket.  I am 
sure I just don't understand what you said below because that doesn't make 
sense.  Thanks for the learning experience thus far.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:444934c4$1@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:44491a72$1@newsgroups.borland.com...
>
>>                         Server->WaitForClientWriteEvent = true;
>>                         while( Server->WaitForClientWriteEvent )
>>                         {
>>                                 Sleep(10);
>>                         }
>
> That will not work.  Non-blocking sockets use window messages internally.
> You must pump the message queue in order for those events to occur.  Which
> then complicates your code because now clients can connect/disconnect 
> while
> you are still looping through them, so your loop can become screwed up
> because your code is currently not set up to handle that situation.
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2403
Author: Remy Lebeau (TeamB)
Date: Mon, 24 Apr 2006 18:08
153 lines
6485 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:444cd08c$1@newsgroups.borland.com...

> Do you think that the Invalid Pointer Exception is coming from
> the client not being present?

That is a possibility, if you are allowing messages to be processed while
you are still looping through the connections.  When a client disconnects,
the OnClientDisconnect event is triggered, and then the server posts a
CM_DEFERFREE message back to itself.  When that message is processed, the
client socket is freed immediately.  If you continue to access the socket
after it has been freed, then your code has undefined behavior from that
point on, and anything can happen.

> The system I have setup should always have a client present; I
> typically (and my test rig is setup this way) only have two client's
> connected to the server application.  They both get the same messages
> no matter what and they should never leave (or disconnect from the
> server).

You should not be relying on that behavior.  You are not allowing your code
to handle unforseen issues, such as network/power outages, transmission
errors, etc.

> Also you stated earlier that I can't keep doing a sendtext until I get
> a ClientWrite Event after a -1 was returned from a SendText.

Please re-read what I said.  What I actually said was that you have to call
WSAGetLastError() in order to find out why SendText() is returning -1.  The
OnWrite event be triggered later on only when WSAGetLastError() returns
WSAEWOULDBLOCK.  Any other value is an actual socket error and the socket
can no longer be used and must be reconnected.

> Now you are saying I have to do a SendText (pump the message queue)
> so I know the state of the socket.

Only for the specific code snippet that you showed, which would not work
given the way you showed it.  You are now relying on a variable that cannot
be set without the OnWrite event being triggered, and it cannot be triggered
while you are still running a loop until the loop pumps the message queue fo
r pending messages.

I strongly suggest that you go to http://www.deja.com and search through the
newsgroup archives.  I have posted sample code dealing with non-blocking
sockets and the OnWrite event on several different occasions.  For example,
here is a more reliable way to deal with queuing outbound data:

    void __fastcall TServer::ServerSocketClientConnect(TObject* Sender,
TCustomWinSocket* Socket)
    {
        Socket->Data = new TMemoryStream;
    }

    void __fastcall TServer::ServerSocketClientDisconnect(TObject* Sender,
TCustomWinSocket* Socket)
    {
        delete static_cast<TMemoryStream*>(Socket->Data);
        Socket->Data = NULL;
    }

    void __fastcall TServer::ServerSocketClientWrite(TObject* Sender,
TCustomWinSocket* Socket)
    {
        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
        if( MS->Size > 0 )
        {
            MS->Position = 0

            LPBYTE ptr = static_cast<LPBYTE>(MS->Memory);
            int sent;

            while( MS->Position < MS->Size )
            {
                sent = Socket->SendBuf(&ptr[MS->Position], MS->Size -
MS->Position);
                if( sent > 0 )
                    MS->Seek(sent, soFromCurrent);
                else
                    break;
            }

            if( MS->Position > 0 )
            {
                int remaining = (MS->Size - MS->Position);
                if( remaining > 0 )
                {
                    if( MS->Position > 0 )
                    {
                        Move(&ptr[MS->Position], MS->Memory, remaining);
                        MS->Size = remaining;
                    }
                }
                else
                    MS->Clear();
            }
        }
    }

    void __fastcall TServer::SendBufferToSocket(TCustomWinSocket *Socket,
void *Buffer, int BufSize)
    {
        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
        LPBYTE ptr = static_cast<LPBYTE>(Buffer);

        if( MS->Size == 0 )
        {
            int sent;

            while( BufSize > 0 )
            {
                sent = Socket->SendBuf(ptr, BufSize);
                if( sent > 0 )
                {
                    ptr += sent;
                    BufSize -= sent;
                    continue;
                }

                if( (sent == 0) || (WSAGetLastError() != WSAEWOULDBLOCK) )
                    return;

                break;
            }

            if( BufSize < 1 )
                return;
        }

        MS->Seek(0, soFromEnd);
        MS->WriteBuffer(ptr, BufSize);
    }

    void __fastcall TServer::SendTextToSocket(TCustomWinSocket *Socket,
const AnsiString &S)
    {
        SendBufferToSocket(Socket, S.c_str(), S.Length());
    }

    void __fastcall TServer::SendMsg(const AnsiString &AMsg)
    {
        for(int ii = 0; ii < ServerSocket1->Socket->ActiveConnections; ++ii)
            SendTextToSocket(ServerSocket1->Socket->Connections[ii], AMsg +
"\n");
    }

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        Server->SendMsg("whatever");
    }


Gambit
Re: TServerSocket SendText Exception
#2410
Author: Eric Patterson
Date: Tue, 25 Apr 2006 17:53
174 lines
7169 bytes
Wow.  That is some tricky stuff.  I always thought you used components to 
make life easy.  If that is the easy version, I would hate to see what that 
component actually does with the window's socket api.  Thanks for the full 
example.  I will see what happens.

Eric


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message 
news:444d14c5@newsgroups.borland.com...
>
> "Eric Patterson" <eric.patterson@bepco.com> wrote in message
> news:444cd08c$1@newsgroups.borland.com...
>
>> Do you think that the Invalid Pointer Exception is coming from
>> the client not being present?
>
> That is a possibility, if you are allowing messages to be processed while
> you are still looping through the connections.  When a client disconnects,
> the OnClientDisconnect event is triggered, and then the server posts a
> CM_DEFERFREE message back to itself.  When that message is processed, the
> client socket is freed immediately.  If you continue to access the socket
> after it has been freed, then your code has undefined behavior from that
> point on, and anything can happen.
>
>> The system I have setup should always have a client present; I
>> typically (and my test rig is setup this way) only have two client's
>> connected to the server application.  They both get the same messages
>> no matter what and they should never leave (or disconnect from the
>> server).
>
> You should not be relying on that behavior.  You are not allowing your 
> code
> to handle unforseen issues, such as network/power outages, transmission
> errors, etc.
>
>> Also you stated earlier that I can't keep doing a sendtext until I get
>> a ClientWrite Event after a -1 was returned from a SendText.
>
> Please re-read what I said.  What I actually said was that you have to 
> call
> WSAGetLastError() in order to find out why SendText() is returning -1. 
> The
> OnWrite event be triggered later on only when WSAGetLastError() returns
> WSAEWOULDBLOCK.  Any other value is an actual socket error and the socket
> can no longer be used and must be reconnected.
>
>> Now you are saying I have to do a SendText (pump the message queue)
>> so I know the state of the socket.
>
> Only for the specific code snippet that you showed, which would not work
> given the way you showed it.  You are now relying on a variable that 
> cannot
> be set without the OnWrite event being triggered, and it cannot be 
> triggered
> while you are still running a loop until the loop pumps the message queue 
> fo
> r pending messages.
>
> I strongly suggest that you go to http://www.deja.com and search through 
> the
> newsgroup archives.  I have posted sample code dealing with non-blocking
> sockets and the OnWrite event on several different occasions.  For 
> example,
> here is a more reliable way to deal with queuing outbound data:
>
>    void __fastcall TServer::ServerSocketClientConnect(TObject* Sender,
> TCustomWinSocket* Socket)
>    {
>        Socket->Data = new TMemoryStream;
>    }
>
>    void __fastcall TServer::ServerSocketClientDisconnect(TObject* Sender,
> TCustomWinSocket* Socket)
>    {
>        delete static_cast<TMemoryStream*>(Socket->Data);
>        Socket->Data = NULL;
>    }
>
>    void __fastcall TServer::ServerSocketClientWrite(TObject* Sender,
> TCustomWinSocket* Socket)
>    {
>        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
>        if( MS->Size > 0 )
>        {
>            MS->Position = 0
>
>            LPBYTE ptr = static_cast<LPBYTE>(MS->Memory);
>            int sent;
>
>            while( MS->Position < MS->Size )
>            {
>                sent = Socket->SendBuf(&ptr[MS->Position], MS->Size -
> MS->Position);
>                if( sent > 0 )
>                    MS->Seek(sent, soFromCurrent);
>                else
>                    break;
>            }
>
>            if( MS->Position > 0 )
>            {
>                int remaining = (MS->Size - MS->Position);
>                if( remaining > 0 )
>                {
>                    if( MS->Position > 0 )
>                    {
>                        Move(&ptr[MS->Position], MS->Memory, remaining);
>                        MS->Size = remaining;
>                    }
>                }
>                else
>                    MS->Clear();
>            }
>        }
>    }
>
>    void __fastcall TServer::SendBufferToSocket(TCustomWinSocket *Socket,
> void *Buffer, int BufSize)
>    {
>        TMemoryStream *MS = static_cast<TMemoryStream*>(Socket->Data);
>        LPBYTE ptr = static_cast<LPBYTE>(Buffer);
>
>        if( MS->Size == 0 )
>        {
>            int sent;
>
>            while( BufSize > 0 )
>            {
>                sent = Socket->SendBuf(ptr, BufSize);
>                if( sent > 0 )
>                {
>                    ptr += sent;
>                    BufSize -= sent;
>                    continue;
>                }
>
>                if( (sent == 0) || (WSAGetLastError() != WSAEWOULDBLOCK) )
>                    return;
>
>                break;
>            }
>
>            if( BufSize < 1 )
>                return;
>        }
>
>        MS->Seek(0, soFromEnd);
>        MS->WriteBuffer(ptr, BufSize);
>    }
>
>    void __fastcall TServer::SendTextToSocket(TCustomWinSocket *Socket,
> const AnsiString &S)
>    {
>        SendBufferToSocket(Socket, S.c_str(), S.Length());
>    }
>
>    void __fastcall TServer::SendMsg(const AnsiString &AMsg)
>    {
>        for(int ii = 0; ii < ServerSocket1->Socket->ActiveConnections; 
> ++ii)
>            SendTextToSocket(ServerSocket1->Socket->Connections[ii], AMsg +
> "\n");
>    }
>
>    void __fastcall TForm1::Button1Click(TObject *Sender)
>    {
>        Server->SendMsg("whatever");
>    }
>
>
> Gambit
>
> 
Re: TServerSocket SendText Exception
#2411
Author: Remy Lebeau (TeamB)
Date: Tue, 25 Apr 2006 21:33
16 lines
1836 bytes
"Eric Patterson" <eric.patterson@bepco.com> wrote in message
news:444e6207$1@newsgroups.borland.com...

> Wow.  That is some tricky stuff.  I always thought you used
> components to make life easy.  If that is the easy version, I
> would hate to see what that component actually does with
> the window's socket api.

That is what happens when you use event-driven components that force you to
divide up your code logic.  A lot of people don't even bother with the
OnWrite event, and then wonder later on why their data sometimes goes
missing.


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