Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TServerSocket SendText Exception

96 views
Skip to first unread message

Eric Patterson

unread,
Apr 17, 2006, 9:47:29 AM4/17/06
to
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


Remy Lebeau (TeamB)

unread,
Apr 17, 2006, 1:02:31 PM4/17/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 17, 2006, 2:07:02 PM4/17/06
to
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....@no.spam.com> wrote in message
news:4443ca2a$1...@newsgroups.borland.com...

Eric Patterson

unread,
Apr 17, 2006, 2:24:09 PM4/17/06
to
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....@no.spam.com> wrote in message
news:4443ca2a$1...@newsgroups.borland.com...
>

Eric Patterson

unread,
Apr 17, 2006, 2:40:58 PM4/17/06
to
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....@no.spam.com> wrote in message
news:4443ca2a$1...@newsgroups.borland.com...
>

Remy Lebeau (TeamB)

unread,
Apr 17, 2006, 5:10:14 PM4/17/06
to

"Eric Patterson" <eric.pa...@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


Remy Lebeau (TeamB)

unread,
Apr 17, 2006, 5:18:52 PM4/17/06
to

"Eric Patterson" <eric.pa...@bepco.com> wrote in message
news:4443...@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


Remy Lebeau (TeamB)

unread,
Apr 17, 2006, 5:21:30 PM4/17/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 19, 2006, 8:19:31 AM4/19/06
to
Thank you for all your help.

Eric


"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4443ca2a$1...@newsgroups.borland.com...
>

Eric Patterson

unread,
Apr 20, 2006, 11:21:28 AM4/20/06
to
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....@no.spam.com> wrote in message
news:4443ca2a$1...@newsgroups.borland.com...
>

Remy Lebeau (TeamB)

unread,
Apr 20, 2006, 12:33:35 PM4/20/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 20, 2006, 1:11:12 PM4/20/06
to
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....@no.spam.com> wrote in message

news:4447b917$3...@newsgroups.borland.com...

Bob Gonder

unread,
Apr 20, 2006, 2:36:23 PM4/20/06
to
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.)

Eric Patterson

unread,
Apr 20, 2006, 2:53:41 PM4/20/06
to
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" <no...@notmindspring.invalid> wrote in message
news:4mkf429644ao82ak6...@4ax.com...

Remy Lebeau (TeamB)

unread,
Apr 20, 2006, 6:24:54 PM4/20/06
to

"Bob Gonder" <no...@notmindspring.invalid> wrote in message
news:4mkf429644ao82ak6...@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


Remy Lebeau (TeamB)

unread,
Apr 20, 2006, 6:23:58 PM4/20/06
to

"Eric Patterson" <eric.pa...@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


Remy Lebeau (TeamB)

unread,
Apr 20, 2006, 6:26:35 PM4/20/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 21, 2006, 7:47:03 AM4/21/06
to
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....@no.spam.com> wrote in message

news:44480b3f$1...@newsgroups.borland.com...

Remy Lebeau (TeamB)

unread,
Apr 21, 2006, 12:42:56 PM4/21/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 21, 2006, 12:52:54 PM4/21/06
to
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....@no.spam.com> wrote in message

news:44480aa5$1...@newsgroups.borland.com...

Eric Patterson

unread,
Apr 21, 2006, 12:54:23 PM4/21/06
to
That makes a ton of sense. I will fix.

Eric


"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message

news:44490c3a$1...@newsgroups.borland.com...

Eric Patterson

unread,
Apr 21, 2006, 12:55:18 PM4/21/06
to
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.pa...@bepco.com> wrote in message

news:44490de6$1...@newsgroups.borland.com...

Eric Patterson

unread,
Apr 21, 2006, 1:46:26 PM4/21/06
to
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....@no.spam.com> wrote in message

news:44480aa5$1...@newsgroups.borland.com...

Remy Lebeau (TeamB)

unread,
Apr 21, 2006, 3:32:51 PM4/21/06
to

"Eric Patterson" <eric.pa...@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


Remy Lebeau (TeamB)

unread,
Apr 21, 2006, 3:36:02 PM4/21/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 24, 2006, 9:20:13 AM4/24/06
to
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....@no.spam.com> wrote in message

news:444934c4$1...@newsgroups.borland.com...

Remy Lebeau (TeamB)

unread,
Apr 24, 2006, 2:08:43 PM4/24/06
to

"Eric Patterson" <eric.pa...@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


Eric Patterson

unread,
Apr 25, 2006, 1:53:12 PM4/25/06
to
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....@no.spam.com> wrote in message

news:444d...@newsgroups.borland.com...

Remy Lebeau (TeamB)

unread,
Apr 25, 2006, 5:33:48 PM4/25/06
to

"Eric Patterson" <eric.pa...@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


0 new messages