tcp port open?
[1/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 9:20
Hi,
Is there a way to now if a tcp port is open on both sides. So that a server
(or client) can see whether or not the other side of the pipe is still open?
Thanks,
Maarten
[2/15] from: petr:krenzelok:trz:cz at: 9-Oct-2001 10:22
Maarten Koopmans wrote:
> Hi,
>
> Is there a way to now if a tcp port is open on both sides. So that a server
> (or client) can see whether or not the other side of the pipe is still open?
I am not sure. Designing our camera we looked at Ethereal
(http://www.ethereal.org) packet monitor, and TCP communication is several
stages process of various ACK, SYN, RST, PSH, FIN type packets. There is no real
connection
on the network, just packets sent here and there. That is why
someone can watch your packets (sniff) and see what you are sending, if
connected to the same network. So, alive connection is just some state in your
tcp stack on your side, irrelevant to other side of "connection". There is also
known case of semi-connection - e.g. one side timeouts, and the other side is
still able to send packets, which are really delivered, just not probably
processed.
So, theoretically, if opposite side sends you FIN or RST assigned packet, you
should note it. This question is, however, for Holger. We have 'query function
available, maybe Rebol somehow knows, if opposite side closed the connection?
-pekr-
[3/15] from: philip:hayes:btcellnet at: 9-Oct-2001 9:53
You should have receive a notification that the connection has dropped
that's the nature of TCP!
[4/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 11:00
I know.... but I can't see that in Rebol.
I am thinking of adding 'persistent connections' to Rugby but I need to know
if the pipe is broken in order to do that.
--Maarten
On Tuesday 09 October 2001 10:53, you wrote:
[5/15] from: petr:krenzelok:trz:cz at: 9-Oct-2001 11:05
Hayes Philip wrote:
> You should have receive a notification that the connection has dropped
> that's the nature of TCP!
Yes, such notification (FIN or RST type packets) is delivered, but to your OS
tcp/ip stack layer. It is not clear however, that Rebol exposes such info
anywhere into the port structure or to be caught by 'querry function ... but,
of course, I can be wrong :-)
-pekr-
[6/15] from: philip:hayes:btcellnet at: 9-Oct-2001 10:21
This is how my tcp-server deals with it
wait-ports: none
listen-port: open/no-wait/direct/binary tcp://:9999
wait-ports: [ listen-port ]
forever [
; Perform asynch wait !!!
wait wait-ports
; Is port descriptor set ?
if not ( none? ( wait [ 0 listen-port ] ) ) [
; Add port to block
append wait-ports first listen-port
]
; Set scope of port checking
check-ports: next wait-ports
; Check port activity ?
while [ ( length? check-ports ) > 0 ] [
conn: first check-ports
; Is port still active ?
either query conn [
; Port active ... so check if any data to be read
either not ( none? ( wait [ 0 conn ] ) ) [
; Yes .. so determine size of data to be
read
readbuffer: copy #{}
readbuffer: copy conn
; If length is none? then connection has
been closed
either none? readbuffer [
; Close down port and tidy up
wait-ports block entry
close conn
remove check-ports
] [
; Is this NOT a HTTP request ?
either none? ( find readbuffer
HTTP/1.
) [
; Remove data from port
clear conn
; Move onto next port
check-ports: next
check-ports
] [
; HTTP request so detrmine
what to do ...
; Remember it's a
non-persistent connection
; Tidy up
clear conn
close conn
]
; VIP - empty out buffer area !!!
clear readbuffer
] ; end of either none? readbuffer
] [
check-ports: next check-ports
]
] [
; Port is no longer active !
; tidy up
clear conn
close conn
remove check-ports
] ; end of query conn
] ; end of while ( length? ...
]
quit
[7/15] from: petr::krenzelok::trz::cz at: 9-Oct-2001 11:33
Maarten Koopmans wrote:
> I know.... but I can't see that in Rebol.
>
> I am thinking of adding 'persistent connections' to Rugby but I need to know
> if the pipe is broken in order to do that.
error? try [insert port stuff] ? That's what Holger suggested me for my FastCGI
problems ...
-pekr-
[8/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 12:52
Phil,
You are correct about the none? with copy
Thanks,
Maarten
[9/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 12:48
copy returns none when there is no data
query returns always true on an opened port regardless of the other side.
So... question remains open.
--Maarten
[10/15] from: philip:hayes:btcellnet at: 9-Oct-2001 12:12
In addition you could place a timeout on the wait
wait wait-ports 600
..and then loop through the port block performing the checks
[11/15] from: sqlab:gmx at: 9-Oct-2001 13:18
> Hi,
> Is there a way to now if a tcp port is open on both sides. So that a
<<quoted lines omitted: 3>>
> Thanks,
> Maarten
Hello Marten
You can either try a read before any sending in order to see, if the
connection is still valid, or if you do a wait on your port-list, you should get the
closing.
Of course, an error? try [sending some data] prevents you from failing, if
the connection is closed during the transmission.
AR
AR
[12/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 13:22
This post was actually send before my thanks, you're right post.
You are right about copy and none
--Maarten
[13/15] from: koopmans:itr:ing:nl at: 9-Oct-2001 13:34
This you shouldn't do when doing a reasonable high-performance server.
I noticed that non-blocking waits eat up CPU.
--Maarten
[14/15] from: g:santilli:tiscalinet:it at: 10-Oct-2001 15:06
Maarten Koopmans wrote:
> Is there a way to now if a tcp port is open on both sides. So that a server
> (or client) can see whether or not the other side of the pipe is still open?
As long as the TCP stack has received the close packet, you can.
If you open the port as /no-wait, using COPY will return (AFAIK):
- a non-empty string, i.e. the data;
- an empty string, meaning the connection is open but there's no
data available in the buffers;
- NONE, meaning the port has been closed on the other side.
HTH,
Gabriele.
--
Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer
Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/
[15/15] from: holger:rebol at: 18-Oct-2001 10:35
On Tue, Oct 09, 2001 at 12:48:49PM +0200, Maarten Koopmans wrote:
> copy returns none when there is no data
> query returns always true on an opened port regardless of the other side.
>
> So... question remains open.
It is a little complicated, unfortunately.
The problem is that TCP is full-duplex, but within the TCP protocol
both directions are logically separated, i.e. a TCP connection
really consists of two half-duplex pipes, each going in one direction.
Both pipes are always created at the same time, when the connection
is opened, but it is possible to close only one of them and keep the
other one open, leading to a "half-closed" connection.
At the TCP protocol level one side can only close its send pipe, not its
receive pipe. The connection is completely closed once both sides have
closed their send pipes. It is possible for a TCP connection to stay
in a half-closed state for an arbitrary amount of time. This is not an
error condition. It is not very common, but some protocols do make use
of it.
It is not possible to close only the receive pipe of a connection.
(The shutdown() function call in C allows that, but for TCP it is
basically a no-op, i.e. the other side is never informed about it, so
even in C closing the receive pipe has no real effect.) What this
means is that with TCP there is no way to tell the other side that
you are no longer willing to accept data.
*Usually* when one side recognizes that the peer has closed its
send pipe, the other side closes its send pipe as well, resulting
in a completely closed connection. This is not always the case though.
For instance with many of the trivial query protocols (daytime, auth
etc.) it is common for the client to send its request and immediately
close its send pipe. Then it waits on its receive pipe for the
server's response. The server only closes its send pipe after sending
its response, even if its receive pipe has been closed by the peer
before it gets a chance to respond.
In order to allow this functionality it is imperative that a server
does not automatically close its send pipe once its receive
pipe has been closed by the peer. Otherwise it would be unable to
respond to requests via a half-closed connection.
What this means for REBOL is:
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.
A query on a port only tells you whether a port is connected at all,
not which pipes of the connection have which state. If the other side
closes its send pipe then you are still connected (because your
send pipe is still open), so query still returns true, and you can
still send data. Of course if the other side actually accepts that
data is a different matter. That depends on whether the other side
only closed its send pipe or whether it completely closed the
socket. There is no way for the local host to detect that, because
that information is not transmitted through TCP.
One exception though: Some, arguably broken, TCP/IP stacks (e.g.
Windows) return errors (RST) to the peer when they receive data for a
socket that has been closed by the program after the program
exits. Most other stacks simply acknowledge the data and throw it
away. For you that means when writing data to a TCP port, and the
receiver is "no longer there" then one of two things may happen:
either your data is silently accepted and ignored, or you may get
an error. Which one it is does not depend on your TCP/IP stack,
but on the peer's TCP/IP stack and how it handles program termination.
Checking whether your incoming side has been closed is NOT the right
way to determine whether the peer is "still there", because you may
get "false positives" on half-closed connections, as explained above.
(Unless, of course, you know that the protocol you are running across
the TCP channel is never supposed to use half-closed connections.
In that case that kind of check is safe.)
At the moment REBOL does not allow you to close only one pipe of a
connection. We plan to add that in one of the next versions, through
get/set-modes.
--
Holger Kruse
[holger--rebol--com]
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted