[ports] [tcp] Detecting peer closing connection
[1/10] from: g:santilli:tiscalinet:it at: 21-Nov-2003 12:22
Hello all,
while doing some tests I and Romano have discovered a strange
behavior in REBOL TCP ports. I thought that, when the peer closes
the TCP connection, you got NONE returned by COPY on the TCP port;
however, it is not always so.
We have discovered that, if there's data in the port output
buffer, and the port is in binary mode, when the peer closes teh
connection you'll get an empty binary (#{}) instead of NONE as the
result of COPY.
This way it becomes difficult to know that the connection was
closed (because empty data also means "no new data available"). If
you are using PORT/AWAKE, however, you can assume that an empty
result is equivalent to NONE, since the AWAKE won't be called if
there's no new data available.
Basically, if your PORT/AWAKE is like this:
port/awake: func [port /local data] [
data: copy port
either data [
do-something-with data
] [
; peer closed connection
close port
; remove it from wait list, etc.
]
]
it won't work if the port, at the time the peer closes the
connection, has data in the send buffer.
You'll have to use, instead:
port/awake: func [port /local data] [
data: copy port
either any [none? data empty? data] [
; peer closed connection
close port
; remove it from wait list, etc.
] [
do-something-with data
]
]
that seems to work in every case. (Note: won't work if you have
ASYNC-MODES set to 'WRITE, since then the AWAKE would be called
even if no data is in the receive buffer.)
I think this issue is the reason why some people (Gregg?) had
problems with async:// when peer closed the connection. I'll fix
my version of async:// soon (but becomes a bit complicated because
of the WRITE async mode).
(BTW, I found the strange behavior, and Romano found out the
reason, so all the credit goes to him. :)
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[2/10] from: rotenca:telvia:it at: 21-Nov-2003 13:39
Hi Gabriele,
> that seems to work in every case. (Note: won't work if you have
> ASYNC-MODES set to 'WRITE, since then the AWAKE would be called
> even if no data is in the receive buffer.)
Yesss, async-modes WRITE uses a forever loop which calls awake forever (use
only when needed).
> (BTW, I found the strange behavior, and Romano found out the
> reason, so all the credit goes to him. :)
You overdo my role :-)
Sent to feedback?
---
Ciao
Romano
[3/10] from: petr:krenzelok:trz:cz at: 21-Nov-2003 14:08
Gabriele Santilli wrote:
>Hello all,
> while doing some tests I and Romano have discovered a strange
<<quoted lines omitted: 10>>
>result is equivalent to NONE, since the AWAKE won't be called if
>there's no new data available.
Hello Gabriele,
I found one earlier post by Holger, well .... I miss his educative
posts so much :-) I don't know if you can find any answers related to
your problem there, but maybe someone other will find it quite educative:
http://www.escribe.com/internet/rebol/m15313.html
>I think this issue is the reason why some people (Gregg?) had
>problems with async:// when peer closed the connection. I'll fix
>my version of async:// soon (but becomes a bit complicated because
>of the WRITE async mode).
>
As for ports bug in general, I reported some strange behavior some time
ago. Win98 scenario, Rebol (don't remember what version), and our device
(8bit chip ethernet + tcp implementation). When we opened port in
open/direct/no-wait, followed by following loop: while [wait port data:
copy port][...], it simply escaped the loop and in Ethereal we could see
PC lowered tcp window to 0 and PC sent RST packet then. Yes, we could
tell that 8bit Scenix chip tcp implementation could be flawed, but the
case was solved by simple adding /binary refinement - so - should
open/direct/no-wait and open/direct/no-wait/binary behave differently?
The rest of the code stayed unchanged. Why without /binary refinement
wait loop was escaped? Could it be related to none vs #{} issue you
describe? The bug was not confirmed by RT and who knows if it is even a
bug, although it seems so. I would have to check with latest Rebol
releases if it is still the same ...
Cheers,
-pekr-
[4/10] from: g::santilli::tiscalinet::it at: 21-Nov-2003 14:18
Hi Romano,
On Friday, November 21, 2003, 1:39:23 PM, you wrote:
RPT> Sent to feedback?
No... would you think it's a bug? Anyway, maybe it's better to
send it...
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[5/10] from: g:santilli:tiscalinet:it at: 21-Nov-2003 14:37
Hi Petr,
On Friday, November 21, 2003, 2:08:32 PM, you wrote:
PK> http://www.escribe.com/internet/rebol/m15313.html
"You can detect whether your receive pipe has been closed by
the peer by performing a 'copy on the port, assuming the port
is in /no-wait mode. A none return means the other side has
closed its send pipe (your receive pipe), any other value means
that your receive pipe is still open."
This means I can assume that the behavior we have observed is a
bug?
PK> case was solved by simple adding /binary refinement - so - should
PK> open/direct/no-wait and open/direct/no-wait/binary behave differently?
I don't think it should in your case, but maybe the code in REBOL
that translates line terminators was interfering somehow?
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[6/10] from: maarten:vrijheid at: 21-Nov-2003 14:37
Hi Gabriele,
I think this may have to do with the port being in async mode? Or did
you test it in sync mode as well?
--Maarten
[7/10] from: g:santilli:tiscalinet:it at: 21-Nov-2003 15:02
Hi Maarten,
On Friday, November 21, 2003, 2:37:06 PM, you wrote:
MK> I think this may have to do with the port being in async mode? Or did
MK> you test it in sync mode as well?
I tested it in sync mode only. I think that Romano tried in async
mode too.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[8/10] from: g:santilli:tiscalinet:it at: 21-Nov-2003 15:22
Hello all,
this is an example of the problem (I'm sending it to feedback
too):
====8<====Console 1=========8<=============8<=============8<>> l: open/binary/no-wait
tcp://:10000
>> p: first l
>> insert/dup p "bla bla " 100
>> copy p
== #{74657374}
>> copy p
== #{}
>> copy p
== #{}
>> copy p
== #{}
>> copy p
== #{}
>> close p
====>8======================>8=============>8=============>8======
====8<====Console 2=========8<=============8<=============8<>> p: open/binary/no-wait
tcp://localhost:10000
>> insert p "test"
>> close p
====>8======================>8=============>8=============>8======
COPY correctly returns NONE if the port send buffer is empty.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[9/10] from: rotenca:telvia:it at: 21-Nov-2003 15:42
Hi Maarten,
> I think this may have to do with the port being in async mode? Or did
> you test it in sync mode as well?
It is the same.
But in async mode, copy should not be used, you must use read-io, and read-io
in this case returns 0 instead of < 0.
---
Ciao
Romano
[10/10] from: greggirwin:mindspring at: 21-Nov-2003 9:50
Hi Gabriele,
GS> I think this issue is the reason why some people (Gregg?) had
GS> problems with async:// when peer closed the connection.
I remember that. I never looked into, but it could relate to how they
handle underlying ports that are half-closed. I remember half-closed
ports as being something you had to consider when I did some winsock
stuff some time back.
-- Gregg
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted