The complete program follows. It is generated from
server-core.c in the companion examples repository.
/* * server-core.c -- raw TCP echo server at the data layer (no WebSocket). * * vws_tcp_svr is the base server: it hands raw inbound bytes to an on_data_in * callback and ships raw bytes back. This also shows the per-worker thread * context (worker_ctor / worker_dtor) -- where a worker holds per-thread * resources (e.g. a database handle) that the data callback receives as its ctx. */ #include <vws/server.h> #include "vwsx.h" #include <stdio.h> #include <string.h> static const char* HOST = "127.0.0.1"; static const int PORT = 8183; /* Per-worker context: created by the ctor, passed to on_data_in as ctx, freed * by the dtor. Here it is just a label, to show the lifecycle. */ static void* worker_ctor(void* data) { (void)data; return vws.strdup("worker-ctx"); } static void worker_dtor(void* ctx) { vws.free(ctx); } /* Echo the raw inbound bytes back to the sender. Runs on a worker thread; ctx * is the per-worker context returned by worker_ctor. */ static void echo(vws_svr_data* req, void* ctx) { (void)ctx; /* Copy the request bytes into a buffer the reply takes ownership of. */ char* data = (char*)vws.malloc(req->size); memcpy(data, req->data, req->size); vws_svr_data* reply = vws_svr_data_own(req->server, req->cid, (ucstr)data, req->size); /* Free the request, then send the reply. */ vws_svr_data_free(req); vws_tcp_svr_send(reply); } int main(void) { vws_tcp_svr* server = vws_tcp_svr_new(10, 0, 0); if (server == NULL) { vwsx_die("vws_tcp_svr_new() failed"); } server->on_data_in = echo; server->worker_ctor = worker_ctor; server->worker_dtor = worker_dtor; /* The base server stops directly -- no cast needed here. */ vwsx_serve_stop_on_signal(server); printf("server-core: raw echo server on %s:%d (Ctrl-C to stop)\n", HOST, PORT); vws_tcp_svr_run(server, HOST, PORT); vws_tcp_svr_free(server); return 0; }