Discussion:
Using TIdTCPClient
(too old to reply)
Mikael Lenfors
2008-06-07 09:17:49 UTC
Permalink
Hello!

I'm about to communicate with an external device over TCP. I am supposed to
send a string of characters and the device will answer with another string
of characters. What methods in the TIdTCPClient am I supposed to use? Is it
the right component in the first place?

I found several methods to send e.g. IdTCPClient.IOHandler.Write and
IdTCPClient.Socket.Write. A'm I supposed to use any of these? Is it possible
to have timeouts on them? If for example the network cable is unplugged?

How should I implemet the recieve? I also here need a timeout if no
characters are returned!

I'm using D2007 and Indy 10. Looked everywhere for examples but couldn't
find any relevant documents...

Regards, Mikael
matthias muntwiler
2008-06-07 17:10:38 UTC
Permalink
Post by Mikael Lenfors
I'm about to communicate with an external device over TCP. I am supposed to
send a string of characters and the device will answer with another string
of characters. What methods in the TIdTCPClient am I supposed to use? Is it
the right component in the first place?
TIdTCPClient should do the job.
Post by Mikael Lenfors
I found several methods to send e.g. IdTCPClient.IOHandler.Write and
IdTCPClient.Socket.Write. A'm I supposed to use any of these?
the highest level method is TIdTCPClient.SendCmd which also checks for a
specific response. if that doesn't fit your protocol, then use one of
the IOHandler.WriteXxxx methods. you can check out the source code of
SendCmd to see an example.
Post by Mikael Lenfors
Is it possible
to have timeouts on them? If for example the network cable is unplugged?
indy will raise an exception if the connection is broken.
Post by Mikael Lenfors
How should I implemet the recieve?
use the IOHandler.Read methods.
Post by Mikael Lenfors
I also here need a timeout if no characters are returned!
look at the TIdTCPClient.ReadTimeout property. some Read methods have
arguments which can override this property.

--matthias
Mikael Lenfors
2008-06-07 18:08:14 UTC
Permalink
Ok, thanks.

I'm trying the folowing:

Cmd := Chr(5) + Chr(1) + Chr(10) + Chr(11) + Chr(12) + Chr(13);
IdTCPClient.IOHandler.WriteLn(Cmd);

Does it only write the 6 characters I specified or does it append any "EOL"
character?

When I read the answer I know how many characters it should be, Can I "Peek"
the puffer and se how many characters are waiting?

Does the ReadLn just get all characters available, or does it wait for any
"EOL" character?

Regards, Mikael
Post by matthias muntwiler
Post by Mikael Lenfors
I'm about to communicate with an external device over TCP. I am supposed
to send a string of characters and the device will answer with another
string of characters. What methods in the TIdTCPClient am I supposed to
use? Is it the right component in the first place?
TIdTCPClient should do the job.
Post by Mikael Lenfors
I found several methods to send e.g. IdTCPClient.IOHandler.Write and
IdTCPClient.Socket.Write. A'm I supposed to use any of these?
the highest level method is TIdTCPClient.SendCmd which also checks for a
specific response. if that doesn't fit your protocol, then use one of the
IOHandler.WriteXxxx methods. you can check out the source code of SendCmd
to see an example.
Post by Mikael Lenfors
Is it possible to have timeouts on them? If for example the network cable
is unplugged?
indy will raise an exception if the connection is broken.
Post by Mikael Lenfors
How should I implemet the recieve?
use the IOHandler.Read methods.
Post by Mikael Lenfors
I also here need a timeout if no characters are returned!
look at the TIdTCPClient.ReadTimeout property. some Read methods have
arguments which can override this property.
--matthias
Remy Lebeau (TeamB)
2008-06-09 17:15:34 UTC
Permalink
Post by Mikael Lenfors
Does it only write the 6 characters I specified or does it
append any "EOL" character?
WriteLn() appends a CRLF to the end of the data. Since your data already
has a Chr(13) in it, you probably want to use Write() instead.
Post by Mikael Lenfors
When I read the answer I know how many characters it should be
Use IOHandler.ReadString() or IOHandler.ReadBytes() for that.
Post by Mikael Lenfors
Can I "Peek" the puffer and se how many characters are waiting?
Not directly. You have to call IOHandler.CheckForDataOnSource() first, and
then you can query the IOHandler.InputBuffer.Size property.
Post by Mikael Lenfors
Does the ReadLn just get all characters available
No.
Post by Mikael Lenfors
or does it wait for any "EOL" character?
By default, it waits for a LF character. ReadLn() has an optional ADelim
parameter that allows you to change which string value to wait for.


Gambit
Yahoo Serious
2008-06-10 08:14:43 UTC
Permalink
Post by Remy Lebeau (TeamB)
Post by Mikael Lenfors
or does it wait for any "EOL" character?
By default, it waits for a LF character. ReadLn() has an optional ADelim
parameter that allows you to change which string value to wait for.
But don't use a terminator string longer than one character. It may get
split across InputBuffers and Indy does not account for that (yet?). E.g.
if you would use "EndOfData" as terminator string, one InputBuffer may
contain "EndOf" and the next InputBuffer may start with "Data". Neither
InputBuffer will match the complete terminator string, and Indy will fail to
detect the terminator string. (Note: CR LF is accidentally handled
correctly.)

(A couple of years ago I ran into this. It took quite some time and
logging, because somehow the InputBufferSize varied inside and outside the
IDE. I suggested to either change the code [as posted back then], or change
"ATerminator: string" to "ATerminator: char".)

Yahoo
Remy Lebeau (TeamB)
2008-06-10 16:54:58 UTC
Permalink
Post by Yahoo Serious
But don't use a terminator string longer than one character.
It may get split across InputBuffers and Indy does not account
for that (yet?).
Yes, it does, and always has. There is only one InputBuffer. ReadLn()
keeps reading from the connection, filling the InputBuffer with more and
more daa, until the requested string value is contained in full inside the
InputBuffer. Why do you thik that does not work?
Post by Yahoo Serious
E.g. if you would use "EndOfData" as terminator string, one
InputBuffer may contain "EndOf" and the next InputBuffer may
start with "Data".
Indy may read the terminator in multiple blocks as you describe, but both
blocks would be concatenated together in the main InputBuffer before then
being checked for the presense of the terminator. I suggest you look at
Indy's actual source code to see what it really does.
Post by Yahoo Serious
Neither InputBuffer will match the complete terminator string
Yes, the main InputBuffer will match.
Post by Yahoo Serious
and Indy will fail to detect the terminator string. (Note: CR LF is
accidentally handled correctly.)
Wrong. CRLF is not handled accidentally. ReadLn() has explicit code to
look for CRLF when LF is the terminator. Again, read the actual source code
before you make such inaccurate claims.
Post by Yahoo Serious
A couple of years ago I ran into this. It took quite some time and
logging, because somehow the InputBufferSize varied inside and
outside the IDE. I suggested to either change the code [as posted
back then], or change "ATerminator: string" to "ATerminator: char".)
Multi-character terminators are supported, and have been for a very long
time.


Gambit
Yahoo Serious
2008-06-12 14:17:43 UTC
Permalink
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
But don't use a terminator string longer than one character.
It may get split across InputBuffers and Indy does not account
for that (yet?).
Yes, it does, and always has. There is only one InputBuffer. ReadLn()
keeps reading from the connection, filling the InputBuffer with more and
more daa, until the requested string value is contained in full inside the
InputBuffer. Why do you thik that does not work?
At a former job I experienced it in Indy 9 (and studied the Indy 10 code for
it). I posted it and you said you would look into it for Indy 10.
Unfortunately, my post remains at my former employer, and I can't find this
post on the web (http://www.atozed.com/WebForums.iwp seems a dead end;
http://newsgroups.cryer.info/atozedsoftware does not have it). However, I
did find Marco Cantu mentioning it for Indy 9 (
http://blog.marcocantu.com/blog/sockets_2chars_separator.html ,
http://blog.marcocantu.com/blog/tale_indy_fix.html ).
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
E.g. if you would use "EndOfData" as terminator string, one
InputBuffer may contain "EndOf" and the next InputBuffer may
start with "Data".
Indy may read the terminator in multiple blocks as you describe, but both
blocks would be concatenated together in the main InputBuffer before then
being checked for the presense of the terminator. I suggest you look at
Indy's actual source code to see what it really does.
The InputBuffer may be concatenated, but to me it looks like it does not
check the complete buffer over and over, but it checks from LSize.
LTermPos := FInputBuffer.IndexOf(ATerminator, LSize);
However, I did not check TIdBuffer.IndexOf, so maybe my interpretation is
wrong.

It is obviously not good to check the same buffer part again, so an offset
to IndexOf is good. But IMHO the starting position should not be the
present LSize (being LTotalInputBufferSizeBeforeThisRead). I think it
should compensate for the length of ATerminator (back then "LSize -
Length(ATerminator)", but Unicode will probably bring a need for a change
there).
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
Neither InputBuffer will match the complete terminator string
Yes, the main InputBuffer will match.
I stand corrected, my memory is not completely correct. The main
InputBuffer will match. However I hink the IndexOf will not (yet)?!
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
and Indy will fail to detect the terminator string. (Note: CR LF is
accidentally handled correctly.)
Wrong. CRLF is not handled accidentally. ReadLn() has explicit code to
look for CRLF when LF is the terminator. Again, read the actual source
code before you make such inaccurate claims.
I don't want to try this all again, but looking at the code I think my
memory is not completely correct (still/again).
But, I think something is off. It looks like if you use LF as ASeparator, a
CR accidentally ending the InputBuffer will be chopped off. I don't think
that would be correct behavior. If I wanted that, I would specify CRLF as
ASeparator, or chop it myself, wouldn't I?
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
A couple of years ago I ran into this. It took quite some time and
logging, because somehow the InputBufferSize varied inside and
outside the IDE. I suggested to either change the code [as posted
back then], or change "ATerminator: string" to "ATerminator: char".)
Multi-character terminators are supported, and have been for a very long
time.
I apologize for my confusion and my false 'accusations'. It's been quite
some time since I ran into this, and I just wanted to save somebody _a lot_
of debugging time.

Yahoo
Remy Lebeau (TeamB)
2008-06-12 17:41:22 UTC
Permalink
Post by Yahoo Serious
It is obviously not good to check the same buffer part again, so an
offset to IndexOf is good. But IMHO the starting position should not
be the present LSize (being LTotalInputBufferSizeBeforeThisRead).
I think it should compensate for the length of ATerminator (back then
"LSize - Length(ATerminator)", but Unicode will probably bring a
need for a change there).
I know for a fact that such logic was in place before, but it seems all
traces of it have disappeared along the way. It will have to be added back
in.
Post by Yahoo Serious
It looks like if you use LF as ASeparator, a CR accidentally
ending the InputBuffer will be chopped off. I don't think that
would be correct behavior. If I wanted that, I would specify
CRLF as ASeparator, or chop it myself, wouldn't I?
If LF is the terminator, then CR alone cannot end a line. Either CRLF or LF
has to be received. Cutting off the CR of a CRLF is NOT accidental. It is
deliberate. The purpose of ReadLn() is to receive a line of text without
the terminating line break. Most internet protocols use CRLF as line
breaks, but not all do. CRLF and LF are treated the same by ReadLn() in
order to handle a wider range of scenerios.


Gambit
Yahoo Serious
2008-06-16 09:09:18 UTC
Permalink
It will have to be added back in.
Thanks in advance.
The purpose of ReadLn() is to receive a line of text without the
terminating line break. Most internet protocols use CRLF as line breaks,
but not all do. CRLF and LF are treated the same by ReadLn() in order to
handle a wider range of scenerios.
Okay, that may be a valid point. Maybe this could be documented/commented in
the code?

ReadLn does not allow for CR as single terminating line break yet (but I
think that is getting obsolete anyway). But more pressing is the question:
does this also imply that the new Tiburon/Unicode variant will also chop off
other Unicode characters which may be considered as a line ending
(http://en.wikipedia.org/wiki/Newline#Unicode: NEL, LS, PS, FF)?

Besides, I think some users are not using a "ReadLn" as such (with the
purpose to receive a line of text), but more as a ReadWithTimeOut (with the
purpose receive data with a time out). [This may even be the reason ReadLn
allows for a different Terminator?] Maybe there could be a separate
"ReadLn"
and "ReadUntilSeparatorWithTimeOut" to prevent any confusion.
Or just an extra parameter AChopLineTerminatorsAtEnding.
Just a thought.

Yahoo.
Remy Lebeau (TeamB)
2008-06-16 17:53:35 UTC
Permalink
Post by Yahoo Serious
ReadLn does not allow for CR as single terminating line break yet
Yes, it does. CR is treated like any other single-character terminator. CR
only has special handling when LF is the terminator.
Post by Yahoo Serious
does this also imply that the new Tiburon/Unicode variant will also
chop off other Unicode characters which may be considered as a
line ending (http://en.wikipedia.org/wiki/Newline#Unicode: NEL,
LS, PS, FF)?
No. ReadLn() chops off whatever terminator is explicitally passed in
(CR/CRLF) is a special case). If ReadLn() implicitally chopped off all
possible line breaks only, than there would be no need for an ATerminator
parameter to begin with. By allowing the caller to pass in a custom
terminator, non-linebreak terminators can be used (and yes, there are
protocols that use such terminators). What you are referring to is just a
small subset of what ReadLn() is designed to support generically.
Post by Yahoo Serious
Besides, I think some users are not using a "ReadLn" as such
(with the purpose to receive a line of text)
Most standardized Internet protocols are line-based textual protocols. Many
of the protocols Indy implements use ReadLn() internally.
Post by Yahoo Serious
but more as a ReadWithTimeOut (with the purpose receive data
with a time out). [This may even be the reason ReadLn allows
for a different Terminator?]
No, that is not why ReadLn() allows custom terminators. A reading timeout
is a completely separate and unrelated feature (which ReadLn() does
support - there is an ATimeout parameter and a ReadLnTimedOut property
available).
Post by Yahoo Serious
Maybe there could be a separate "ReadLn" and
"ReadUntilSeparatorWithTimeOut"
to prevent any confusion.
There is no need to do that.


Gambit
Yahoo Serious
2008-06-17 08:01:15 UTC
Permalink
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
ReadLn does not allow for CR as single terminating line break yet
Yes, it does. CR is treated like any other single-character terminator.
CR only has special handling when LF is the terminator.
What I mean is: if you define ATerminator to be LF or empty (which defaults
to LF), this is interpreted as "receive a line of text without the
terminating line break". Then both LF and CRLF are considered a terminator
and removed. But CR alone is not considered a terminator (and not removed)
in this scenario.

If one would define ATerminator to be CR, it would not remove LF and CRLF.
So my point is, that using LF as "receive a line of text without the
terminating line break", is not handling all the cases (be it infrequent
ones) one may expect in this interpretation.
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
does this also imply that the new Tiburon/Unicode variant will also
chop off other Unicode characters which may be considered as a
line ending (http://en.wikipedia.org/wiki/Newline#Unicode: NEL,
LS, PS, FF)?
No. ReadLn() chops off whatever terminator is explicitally passed in
(CR/CRLF) is a special case). If ReadLn() implicitally chopped off all
possible line breaks only, than there would be no need for an ATerminator
parameter to begin with. By allowing the caller to pass in a custom
terminator, non-linebreak terminators can be used (and yes, there are
protocols that use such terminators). What you are referring to is just a
small subset of what ReadLn() is designed to support generically.
If one can use/interpret ATerminator=LF as "receive a line of text without
the terminating line break", then I think this interpretation should handle
all cases. So it should also handle these Unicode-breaks.
I understand this would complicate the code, so if I were you I would not do
it. And I would also keep CRLF when using LF, for backward compatibility.
But I would be sure to document this behavior, since I would consider it
unexpected and incosistent.
Post by Remy Lebeau (TeamB)
Most standardized Internet protocols are line-based textual protocols.
And how will those protocols handle lines ending in just CR, NEL, or LS?
Post by Remy Lebeau (TeamB)
No, that is not why ReadLn() allows custom terminators. A reading timeout
is a completely separate and unrelated feature (which ReadLn() does
support - there is an ATimeout parameter and a ReadLnTimedOut property
available).
ReadLn is the only public method available to read using a time out (which
is also implied by the property name ReadLnTimedOut). So I agree it is a
completely unrelated feature, but (unfortunately) it is not [implemented]
completely separate.
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
Maybe there could be a separate "ReadLn" and
"ReadUntilSeparatorWithTimeOut" to prevent any confusion.
There is no need to do that.
IMO it would complicate implementation, but it would clarify behavior.
But I'll settle for support for multi character terminators ;-)

Yahoo.
Remy Lebeau (TeamB)
2008-06-17 17:00:01 UTC
Permalink
Post by Yahoo Serious
What I mean is: if you define ATerminator to be LF or empty
(which defaults to LF), this is interpreted as "receive a line of
text without the terminating line break".
ReadLn() always strips off whatever terminator is specified. For example:

line := TCPClient.ReadLn('end');

If ReadLn() receives 'this is the end' then only 'this is the ' will be
returned. That is by design.
Post by Yahoo Serious
Then both LF and CRLF are considered a terminator and removed.
I already explained why that is.
Post by Yahoo Serious
But CR alone is not considered a terminator (and not removed) in this
scenario.
If CR is the sole terminator, it will be stripped off as expected when
ReadLn() receives a line with CR in it. If ReadLn() received a CRLF rather
than just a CR, the LF will be preserved (though it will be carried over to
the next ReadLn() call). Again, that is by design. CR by itself is a valid
single-character terminator, and will be treated as such. LF by itself
refers to both CRLF and LF as a terminator. CRLF is a special case for
reasons I have already explained.
Post by Yahoo Serious
If one would define ATerminator to be CR, it would not remove LF and CRLF.
It is not supposed to, by design.
Post by Yahoo Serious
So my point is, that using LF as "receive a line of text without
the terminating line break", is not handling all the cases
It is not supposed to, by design. Again, CRLF is a single special case in
order to handle most Internet protocols. Stop reading too much into this.
You keep misinterpretting what ReadLn() does.
Post by Yahoo Serious
If one can use/interpret ATerminator=LF as "receive a line of
text without the terminating line break"
That is not what it means. You are misinterpretting it. ATerminator=LF
means only LF and CRLF exclusively. Nothing else. It does NOT mean "all
possible line breaks".
Post by Yahoo Serious
then I think this interpretation should handle all cases.
No, it should not, because that is the wrong interpretation to begin with.
Post by Yahoo Serious
So it should also handle these Unicode-breaks.
No can do. Do you know how many Unicode line breaks there actually are? Do
you really want ReadLn() to waste time and memory checking for all of them?
And for what? Most protocols don't use them anyway. If you want to support
them, then derive your own client code that checks for them as needed.
Post by Yahoo Serious
Post by Remy Lebeau (TeamB)
Most standardized Internet protocols are line-based textual protocols.
And how will those protocols handle lines ending in just CR, NEL, or LS?
Have you read any RFCs for any Internet protocols? Any protocol that is
based on textual lines has to explicitally define which line breaks are
actually valid for the protocol. Most protocols use CRLF exclusively. In
fact, most protocols are ASCII based only, so Unicode line breaks don't
apply anyway. Any protocol that wants to support Unicode generally has to
use UTF-8 or other encoding so Unicode data stays within the confines of the
ASCII subset for the procotol. So Unicode line breaks still would not apply
when reading lines from the connection.
Post by Yahoo Serious
ReadLn is the only public method available to read using a time out
No, it is not. The connection's ReadTimeout property applies to all of the
reading methods equally. It just happens that ReadLn() also has its own
ATimeout parameter on top of that. When ATimeout is IdTimeoutDefault, the
ReadTimeout property is used instead. This allows per-line timeouts to be
specified. But most usages of ReadLn() do not make use of that feature.
Post by Yahoo Serious
which is also implied by the property name ReadLnTimedOut
That property exists for convenience. There are cases where protocol
handlers want to know if a line timed out, without using exception handlers
to detect that.
Post by Yahoo Serious
So I agree it is a completely unrelated feature, but (unfortunately) it is
not [implemented] completely separate.
Yes, it is implemented separately. ReadLn()'s timeout handling is just
extra handling on top of the generic timeout handling that applies to the
entire connection as a whole.
Post by Yahoo Serious
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
Maybe there could be a separate "ReadLn" and
"ReadUntilSeparatorWithTimeOut" to prevent any confusion.
There is no need to do that.
IMO it would complicate implementation, but it would clarify behavior.
Not really. Considering that ReadLn() already has an ATimeout parameter
that is visible and documented, having a separate
ReadUntilSeparatorWithTimeOut() method is just redundant and a waste of
code.
Post by Yahoo Serious
But I'll settle for support for multi character terminators ;-)
It has already been implemented. I checked in some new code last night.


Gambit
Yahoo Serious
2008-06-19 09:17:40 UTC
Permalink
ATerminator=LF means only LF and CRLF exclusively. Nothing else. It does
NOT mean "all possible line breaks".
Then please have someone document this clearly. If I go to the help for
"TIdIOHandler, ReadLn" this brings me to
<ms-help://borland.bds5/Indy/frames.html?frmname=topic&frmfile=TIdIOHandler_ReadLn.html>.
It states: "ReadLn is a String function that returns a a single line from
the input buffer maintained for the IOHandler. This variant of the ReadLn
method uses the LF character as the end-of-line delimiter, and calls an
overloaded variant of the method."
And: "All ATerminator characters in the return value for ReadLn (including
CR and LF characters) are removed prior to exiting from the method."
It does not state "If LF is the terminator, CRLF and LF are treated the same
by ReadLn() in order to handle a wider range of scenarios."
Post by Yahoo Serious
So it should also handle these Unicode-breaks.
No can do. [..]
Most protocols don't use them anyway. If you want to support them, then
derive your own client code that checks for them as needed.
No will do. I'm all for detecting what the parameter explicitly specifies.
I'm not wanting an unspecified, unannounced wider range of scenarios.
So Unicode line breaks still would not apply when reading lines from the
connection.
Okay.
The connection's ReadTimeout property applies to all of the reading
methods equally. It just happens that ReadLn() also has its own ATimeout
parameter on top of that.
Okay.
Post by Yahoo Serious
But I'll settle for support for multi character terminators ;-)
It has already been implemented. I checked in some new code last night.
Thanks,
Yahoo.
Remy Lebeau (TeamB)
2008-06-19 18:44:42 UTC
Permalink
Post by Yahoo Serious
Then please have someone document this clearly.
It already is.
Post by Yahoo Serious
It states: "ReadLn is a String function that returns a a single line
from the input buffer maintained for the IOHandler. This variant
of the ReadLn method uses the LF character as the end-of-line
delimiter, and calls an overloaded variant of the method."
You are looking at the ReadLn() overload that does not have an ATerminator
parameter.
Post by Yahoo Serious
And: "All ATerminator characters in the return value for ReadLn
(including CR and LF characters) are removed prior to exiting from
the method."
In other words, ReadLn() reads from the connection up to, and including,
whatever ATerminator is specified, and then truncates the ATerminator from
the result.
Post by Yahoo Serious
It does not state "If LF is the terminator, CRLF and LF are treated the
same by ReadLn() in order to handle a wider range of scenarios."
It doesn't need to. However, it does already the possibility of EOL being
used as a terminator.


Gambit
Yahoo Serious
2008-06-20 10:06:39 UTC
Permalink
Post by Remy Lebeau (TeamB)
You are looking at the ReadLn() overload that does not have an ATerminator
parameter.
Delphi (ms-help://borland.bds5/Indy) just offered me this one. But after
looking very closely I found another one. Under "Read Operations" you only
get "ReadLn()", but under "Methods" there are two.

http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdIOHandler_ReadLn.html
Gives the same Help. But if you click "Related Methods > IoHandler Members"
and then select (the single) "ReadLn" you actually get to choose which
ReadLn.
Post by Remy Lebeau (TeamB)
Post by Yahoo Serious
It does not state "If LF is the terminator, CRLF and LF are treated the
same by ReadLn() in order to handle a wider range of scenarios."
It doesn't need to. However, it does already the possibility of EOL being
used as a terminator.
Well, I thinks the discussion is maybe starting to get too detailed, but
anyway.
Help states:
---
If data is expected and you do not need a custom end-of-line symbol, you can
use the default ATerminator value or one of the following:
Char Description
LF Line Feed (Decimal 10)
CR Carriage Return (Decimal 13)
EOL End-of-line (Carriage Return + Line Feed)
---
It does not state: if you use the default LF, it also detects/strips EOL.
If this was supposed to imply that, then it also would imply that CR alone
is detected/stripped. And it would also imply that using CR alone also
detects/strips EOL.

Help also states:
---
All ATerminator characters in the return value for ReadLn (including CR
characters) are removed prior to exiting from the method.
---

To me it seems to suggest either:
- if ATerminator contains a CR, CR is also stripped
- ATerminator is stripped and CR is also stripped
Neither one is correct. It does not mention LF, nor does it mention CR has
to be at the end of the remaining string.

As I said 'maybe too detailed', but I think it's not correct yet.

Yahoo.

[PS: Actually, if someone will change it, maybe they could also change
"ATerminator characters" into "ATerminator strings". Indy is not looking
for "characters" but for a "character sequence" or string. But I realize
I'm really splitting hairs now.]

Remy Lebeau (TeamB)
2008-06-09 17:10:13 UTC
Permalink
Post by matthias muntwiler
indy will raise an exception if the connection is broken.
But not until the OS reports errors on the connection first. When
unplugging the network cable, the OS may not see that for a LONG time, and
would not report errors on the connection in the meantime.


Gambit
Loading...