14.3.1 TCP
For information about TCP in general, see TCP/IP Illustrated, Volume 1 by W. Richard Stevens.
procedure
(tcp-listen port-no [ max-allow-wait reuse? hostname]) → tcp-listener? port-no : (integer-in 0 65535) max-allow-wait : exact-nonnegative-integer? = 4 reuse? : any/c = #f hostname : (or/c string? #f) = #f
If the reuse? argument is true, then tcp-listen will create a listener even if the port is involved in a TIME_WAIT state. Such a use of reuse? defeats certain guarantees of the TCP protocol; see Stevens’s book for details. Furthermore, on many modern platforms, a true value for reuse? overrides TIME_WAIT only if the listener was previously created with a true value for reuse?.
If hostname is #f (the default), then the listener accepts connections to all of the listening machine’s addresses. Otherwise, the listener accepts connections only at the interface(s) associated with the given hostname. For example, providing "127.0.0.1" as hostname creates a listener that accepts only connections to "127.0.0.1" (the loopback interface) from the local machine.
(Racket implements a listener with multiple sockets, if necessary, to accommodate multiple addresses with different protocol families. On Linux, if hostname maps to both IPv4 and IPv6 addresses, then the behavior depends on whether IPv6 is supported and IPv6 sockets can be configured to listen to only IPv6 connections: if IPv6 is not supported or IPv6 sockets are not configurable, then the IPv6 addresses are ignored; otherwise, each IPv6 listener accepts only IPv6 connections.)
The return value of tcp-listen is a TCP listener. This value can be used in future calls to tcp-accept, tcp-accept-ready?, and tcp-close. Each new TCP listener value is placed into the management of the current custodian (see Custodians).
If the server cannot be started by tcp-listen, the exn:fail:network exception is raised.
A TCP listener can be used as a synchronizable event (see Events). A TCP listener is ready for synchronization when tcp-accept would not block; the synchronization result of a TCP listener is the TCP listener itself.
procedure
(tcp-connect hostname port-no [ local-hostname local-port-no]) →
input-port? output-port? hostname : string? port-no : (integer-in 1 65535) local-hostname : (or/c string? #f) = #f local-port-no : (or/c (integer-in 1 65535) #f) = #f
(If hostname is associated with multiple addresses, they are tried one at a time until a connection succeeds. The name "localhost" generally specifies the local machine.)
The optional local-hostname and local-port-no specify the client’s address and port. If both are #f (the default), the client’s address and port are selected automatically. If local-hostname is not #f, then local-port-no must be non-#f. If local-port-no is non-#f and local-hostname is #f, then the given port is used but the address is selected automatically.
Two values are returned by tcp-connect: an input port and an output port. Data can be received from the server through the input port and sent to the server through the output port. If the server is a Racket program, it can obtain ports to communicate to the client with tcp-accept. These ports are placed into the management of the current custodian (see Custodians).
Initially, the returned input port is block-buffered, and the returned output port is block-buffered. Change the buffer mode using file-stream-buffer-mode.
Both of the returned ports must be closed to terminate the TCP connection. When both ports are still open, closing the output port with close-output-port sends a TCP close to the server (which is seen as an end-of-file if the server reads the connection through a port). In contrast, tcp-abandon-port (see below) closes the output port, but does not send a TCP close until the input port is also closed.
Note that the TCP protocol does not support a state where one end is willing to send but not read, nor does it include an automatic message when one end of a connection is fully closed. Instead, the other end of a connection discovers that one end is fully closed only as a response to sending data; in particular, some number of writes on the still-open end may appear to succeed, though writes will eventually produce an error.
If a connection cannot be established by tcp-connect, the exn:fail:network exception is raised.
procedure
(tcp-connect/enable-break hostname port-no [ local-hostname] local-port-no)
→
input-port? output-port? hostname : string? port-no : (integer-in 1 65535) local-hostname : (or/c string? #f) = #f local-port-no : (or/c (integer-in 1 65535) #f)
procedure
(tcp-accept listener) →
input-port? output-port? listener : tcp-listener?
Two values are returned by tcp-accept: an input port and an output port. Data can be received from the client through the input port and sent to the client through the output port. These ports are placed into the management of the current custodian (see Custodians).
In terms of buffering and connection states, the ports act the same as ports from tcp-connect.
If a connection cannot be accepted by tcp-accept, or if the listener has been closed, the exn:fail:network exception is raised.
procedure
(tcp-accept/enable-break listener) →
input-port? output-port? listener : tcp-listener?
procedure
(tcp-accept-ready? listener) → boolean?
listener : tcp-listener?
If the listener has been closed, the exn:fail:network exception is raised.
procedure
listener : tcp-listener?
If the listener has already been closed, the exn:fail:network exception is raised.
The listener’s port number may not become immediately available for new listeners (with the default reuse? argument of tcp-listen). For further information, see Stevens’s explanation of the TIME_WAIT TCP state.
procedure
(tcp-listener? v) → boolean?
v : any/c
procedure
(tcp-accept-evt listener) → evt?
listener : tcp-listener?
procedure
(tcp-abandon-port tcp-port) → void?
tcp-port : tcp-port?
The TCP protocol does not include a “no longer reading” state on connections, so tcp-abandon-port is equivalent to close-input-port on input TCP ports.
procedure
(tcp-addresses tcp-port [port-numbers?])
→
(or/c (values string? string?) (values string? (integer-in 1 65535) string? (integer-in 0 65535))) tcp-port : (or/c tcp-port? tcp-listener?) port-numbers? : any/c = #f
If port-numbers? is true, then four results are returned: a string for the local machine’s address, an exact integer between 1 and 65535 for the local machine’s port number, a string for the remote machine’s address, and an exact integer between 1 and 65535 for the remote machine’s port number or 0 for a listener.
If the given port has been closed, the exn:fail:network exception is raised.