Netcat is a well known networking tool that can do tons of things. Arguably, the most common use case is reading data from a remote TCP or UDP endpoint and write it to the stdio, or vice versa. For example, this is how a simple HTTP request could be made with Netcat:

$ echo -e "GET /\n" | nc google.com 80
HTTP/1.0 302 Found
Cache-Control: private

In this blogpost, I am going to show you how this basic netcat functionality can be implemented with Mongoose. As always, the full source code of this example is available on Github - all you need to do is to clone the repo and type “make” in the example directory.

Netcat can be started as either a client or a server. If the “-l” command line option is given, netcat starts as a server, otherwise it starts as a client. The mandatory command line option specifies an address to listen on or to connect to. In Mongoose format host:port. For example, to start a local listener on port 8000:

$ nc -l 8000

Then, the listening or outbound network connection is initialised:

if (is_listening) {
if (mg_bind(&mgr, address, ev_handler) == NULL) {
fprintf(stderr, "mg_bind(%s) failed\n", address);
exit(EXIT_FAILURE);
}
} else if (mg_connect(&mgr, address, ev_handler) == NULL) {
fprintf(stderr, "mg_connect(%s) failed\n", address);
exit(EXIT_FAILURE);
}

The core of the functionality is in the event handler function. When the connection is established (or incoming connection accepted), we run a separate thread that does stdio. On receipt of data, we dump received data to the stdout and clear the receive buffer:

static void ev_handler(struct mg_connection *nc, int ev, void *p) {
(void) p;
switch (ev) {
case MG_EV_ACCEPT:
case MG_EV_CONNECT:
mg_start_thread(stdio_thread_func, nc->mgr);
break;
case MG_EV_CLOSE:
s_received_signal = 1;
break;
case MG_EV_RECV:
fwrite(nc->recv_mbuf.buf, 1, nc->recv_mbuf.len, stdout);
mbuf_remove(&nc->recv_mbuf, nc->recv_mbuf.len);
break;
default:
break;
}
}

When users type something on a console, the stdio reader thread catches that and signals the network IO thread to push the data by calling mg_broadcast():

while ((ch = getchar()) != EOF) {
mg_broadcast(mgr, on_stdin_read, &ch, sizeof(ch));
}

To contact: send us a message or ask on the developer forum.