.. zsh-module-meta::
   :name: zsh/net/tcp
   :summary: Manipulation of TCP sockets

The ``zsh/net/tcp`` module makes available one builtin command:

.. index:: single: ztcp; Function

.. index:: single: TCP; Command

.. index:: single: sockets, TCP; Command

``ztcp`` [ ``-acflLstv`` ] [ ``-d`` :var:`fd` ] [ :var:`args` ]
    
    ``ztcp`` is implemented as a builtin to allow full use of shell
    command line editing, file I/O, and job control mechanisms.
    
    If ``ztcp`` is run with no options, it will output
    the contents of its session table.
    
    If it is run with only the option ``-L``, it will output the contents of
    the session table in a format suitable for automatic parsing.  The option
    is ignored if given with a command to open or close a session.  The output
    consists of a set of lines, one per session, each containing the following
    elements separated by spaces:
    
    
    File descriptor
        
        The file descriptor in use for the connection.  For normal inbound (``I``)
        and outbound (``O``) connections this may be read and written by the usual
        shell mechanisms.  However, it should only be closed with ``ztcp -c``.
        
    
    Connection type
        
        A letter indicating how the session was created:
        
        
        ``Z``
            
            A session created with the ``zftp`` command.
            
        
        ``L``
            
            A connection opened for listening with ``ztcp -l``.
            
        
        ``I``
            
            An inbound connection accepted with ``ztcp -a``.
            
        
        ``O``
            
            An outbound connection created with ``ztcp`` :var:`host` :var:`...`.
            
        
        ``S``
            
            A connection that has been shut down with ``ztcp -s``.
            
        
        
        
        
    
    The local host
        
        This is usually set to an all-zero IP address as the address of the
        localhost is irrelevant.
        
    
    The local port
        
        This is likely to be zero unless the connection is for listening.
        
    
    The remote host
        
        This is the fully qualified domain name of the peer, if available, else an
        IP address.  It is an all-zero IP address for a session opened for
        listening.
        
    
    The remote port
        
        This is zero for a connection opened for listening.
        
    
    
    

Outbound Connections
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index:: single: sockets, outbound TCP; Command

``ztcp`` [ ``-v`` ] [ ``-d`` :var:`fd` ] :var:`host` [ :var:`port` ]
    
    Open a new TCP connection to :var:`host`.  If the :var:`port` is
    omitted, it will default to port 23.  The connection will
    be added to the session table and the shell parameter
    ``REPLY`` will be set to the file descriptor associated
    with that connection.
    
    If ``-d`` is specified, its argument will be taken as the target file
    descriptor for the connection.
    
    In order to elicit more verbose output, use ``-v``.
    

Inbound Connections
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index:: single: sockets, inbound TCP; Command

``ztcp`` ``-l`` [ ``-v`` ] [ ``-d`` :var:`fd` ] :var:`port`
    
    ``ztcp -l`` will open a socket listening on TCP
    :var:`port`.  The socket will be added to the
    session table and the shell parameter ``REPLY``
    will be set to the file descriptor associated
    with that listener.
    
    If ``-d`` is specified, its argument will be taken as the target file
    descriptor for the connection.
    
    In order to elicit more verbose output, use ``-v``.
    

``ztcp`` ``-a`` [ ``-tv`` ] [ ``-d`` :var:`targetfd` ] :var:`listenfd`
    
    ``ztcp -a`` will accept an incoming connection
    to the port associated with :var:`listenfd`.
    The connection will be added to the session
    table and the shell parameter ``REPLY`` will
    be set to the file descriptor associated with
    the inbound connection.
    
    If ``-d`` is specified, its argument
    will be taken as the target file descriptor for the
    connection.
    
    If ``-t`` is specified, ``ztcp`` will return
    if no incoming connection is pending.  Otherwise
    it will wait for one.
    
    In order to elicit more verbose output, use ``-v``.
    

Closing Connections
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index:: single: sockets, closing TCP; Command

``ztcp`` ``-s`` :var:`fd`
    
    ``ztcp -s`` will shut down the socket associated
    with :var:`fd`. This means a graceful termination
    of the connection is initiated, flushing unsent
    data (due to Nagle's algorithm, for example). To
    complete it, you should also drain any remaining
    data on the fd by reading it. Afterwards you should
    use ``ztcp -c`` to close the fd. If you close it
    without first using ``ztcp -s`` and draining the
    data, the kernel may reset the connection, causing
    data you sent to not be received by the other end.
    
    Note that this is only useful for inbound and
    outbound connections, not for listening sockets.
    

``ztcp`` ``-cf`` [ ``-v`` ] [ :var:`fd` ]

``ztcp`` ``-c`` [ ``-v`` ] [ :var:`fd` ]
    
    ``ztcp -c`` will close the socket associated
    with :var:`fd`.  The socket will be removed from the
    session table.  If :var:`fd` is not specified,
    ``ztcp`` will close everything in the session table.
    
    See also the previous ``ztcp -s`` entry.
    
    Normally, sockets registered by zftp (see
    :zshsectref:`The zsh/zftp Module <zshmodules>`)
    cannot be closed this way.  In order
    to force such a socket closed, use ``-f``.
    
    In order to elicit more verbose output, use ``-v``.
    

Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index:: single: TCP, example; Command

Here is how to create a TCP connection between two instances of zsh.  We
need to pick an unassigned port; here we use the randomly chosen 5123.

On ``host1``,

.. code-block:: zsh
   :class: example

    zmodload zsh/net/tcp
    ztcp -l 5123
    listenfd=$REPLY
    ztcp -a $listenfd
    fd=$REPLY

The second from last command blocks until there is an incoming connection.

Now create a connection from ``host2`` (which may, of course, be the same
machine):

.. code-block:: zsh
   :class: example

    zmodload zsh/net/tcp
    ztcp host1 5123
    fd=$REPLY

Now on each host, ``$fd`` contains a file descriptor for talking to the
other.  For example, on ``host1``:

.. code-block:: zsh
   :class: example

    print This is a message >&$fd

and on ``host2``:

.. code-block:: zsh
   :class: example

    read -r line <&$fd; print -r - $line

prints ``This is a message``.

To tidy up, on ``host1``:

.. code-block:: zsh
   :class: example

    ztcp -c $listenfd
    ztcp -s $fd
    ztcp -c $fd

and on ``host2``

.. code-block:: zsh
   :class: example

    ztcp -s $fd
    ztcp -c $fd

