Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changes between Initial Version and Version 1 of NetworkAPITutorial

2016-03-11T16:10:43Z (7 years ago)
Jiri Svoboda

Start tutorial on networking API


  • NetworkAPITutorial

    v1 v1  
     1= HelenOS Network Transport API tutorial =
     3This tutorial is a set of step by step guide to creating a simple network application in HelenOS that communicates over TCP or UDP.
     5== Introduction ==
     7HelenOS network stack was designed and written from scratch. Its APIs do not mimic any existing preexisting interfaces (such as BSD sockets). This allows us the freedom to design more sleek and modern APIs compared to just sticking with the legacy APIs.
     9This means the programmer needs to learn new APIs. However the learning curve is not steep and somebody who knows BSD sockets should be able to learn them quickly. In synchronous modes the mapping from one API to another is not too complicated.
     11== TCP client ==
     13Here we describe how to create an application that connects to a remote server via TCP.
     15We'll need to include the following headers:
     18#include <inet/endpoint.h>
     19#include <inet/hostport.h>
     20#include <inet/tcp.h>
     23Suppose we want the user to specify the host name (or address) and port to connect to. The user will supply it as a host:port string in the 'hostport' variable.
     25We need to declare and initialize an endpoint pair - a data type which can hold both a remote and local endpoint (address:port pair).
     28inet_ep2_t epp;
     32After calling inet_ep2_init() the endpoint is fully unspecified. Now we'll parse the hostport string and save the result to the 'remote' endpoint. Thus we'll have specified to which host and port we want to connect to:
     35char *errmsg;
     36rc = inet_hostport_plookup_one(hostport, ip_any, &epp.remote, NULL, &errmsg);
     37if (rc = EOK) {
     38        printf("Error: %s (host:port %s).\n", errmsg, hostport);
     39        goto error;
     42Note that the 'hostport' string can contain either a host name or a literal IP address. Here are some examples of valid host:port strings:
     44 * {{{}}} (with a host name)
     45 * {{{}}} (with an IPv4 address literal)
     46 * {{{[2001:db8::23]:1234}}} (with a literal IPv6 address)
     48The argument ip_any means that we're willing to work with any IP protocol version (and the system should select an appropriate one).
     50We need to create an object representing the TCP service.
     53tcp_t *tcp;
     54rc = tcp_create(&tcp);
     55if (rc != EOK)
     56        goto error;
     59We can now initiate the connection:
     62tcp_conn_t *conn;
     63rc = tcp_conn_create(tcp, &epp, &conn_cb, NULL, &conn);
     64if (rc != EOK)
     65        goto error;
     68Here {{{&epp}}} is the endpoint pair which specifies the local and remote endpoints. Note that if a local address is not provided, it is automatically selected. If a local port is not provided, it is allocated from the set of ephemeral ports.
     70{{{&conn_cb}}} is a pointer to the structure of type {{{tcp_cb_t}}} containing callbacks to be used with the connection. {{{NULL}}} is a user argument that can be used by the user's callback functions. The callback structure is defined as:
     73/** TCP connection callbacks */
     74typedef struct tcp_cb {
     75        void (*connected)(tcp_conn_t *);
     76        void (*conn_failed)(tcp_conn_t *);
     77        void (*conn_reset)(tcp_conn_t *);
     78        void (*data_avail)(tcp_conn_t *);
     79        void (*urg_data)(tcp_conn_t *);
     80} tcp_cb_t;
     83All the callbacks are optional, i.e. the user only needs to specify handlers for the events he is interested in.
     85The function {{{tcp_conn_create()}}} returns immediately and does not wait for the connection to be established. If we want to block until the connection is established, we can call:
     88rc = tcp_conn_wait_connected(conn);
     89if (rc != EOK)
     90        goto error;
     93Alternatively, we can use callbacks to determine connection progress.
     94 * {{{void (*connected)(tcp_conn_t *)}}} when connection was established
     95 * {{{void (*conn_failed)(tcp_conn_t *)}}} when the attempt to connect is given up
     97To send data we can simply use:
     100int rc = tcp_conn_send(conn, data, size);
     104note that the function may block until space is available in the connection's outbound buffer. If we don't want to send data anymore, we can close the outbound half of the connection with:
     107rc = tcp_conn_send_fin(conn);
     110Note that we can still continue to receive data on the connection after that.
     112To receive data:
     115rc = tcp_conn_recv(conn, recv_buf, RECV_BUF_SIZE, &nrecv);
     118The function {{{tcp_conn_recv()}}} blocks until some data is available. On success it returns {{{EOK}}} and places the number of received bytes in {{{nrecv}}}.
     120To receive data in an asynchronous manner, we can register for the callback
     121 * {{{void (*data_avail)(tcp_conn_t *)}}}
     123This callback is invoked when new data is received on the connection. The user's callback handler should then pick up all available data.
     125Here's an example how the callback handler might look like:
     128static void example_data_avail(tcp_conn_t *conn)
     130        int rc;
     131        size_t nrecv;
     133        while (true) {
     134                rc = tcp_conn_recv(conn, recv_buf, RECV_BUF_SIZE, &nrecv);
     135                if (rc != EOK) {
     136                        printf("Receive error %d\n", rc);
     137                        break;
     138                }
     140                example_data_received(recv_buf, nrecv);
     142                if (nrecv != RECV_BUF_SIZE)
     143                        break;
     144        }
     148Another callback that can be registered is
     149 * {{{void (*conn_reset)(tcp_conn_t *)}}}
     150which informs us that the connection was reset by the peer. No more data can be sent or received afterwards and the only option is to destroy the connection.
     152When we are done with a connection we want to destroy it. When we are done with all TCP communications we want to destroy the TCP service object.
     160= TCP server =
     164= UDP client =
     168= UDP server =