Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] Re: tcp port open?

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]