Skip to content

Instantly share code, notes, and snippets.

@zYeoman
Forked from martinsik/index.html
Last active May 6, 2022 16:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save zYeoman/8dffbb612d10c3a11912cb26027f4236 to your computer and use it in GitHub Desktop.
Save zYeoman/8dffbb612d10c3a11912cb26027f4236 to your computer and use it in GitHub Desktop.
Simple WebSocket server based on libwebsockets. For full description read http://martinsikora.com/libwebsockets-simple-websocket-server
gcc libwebsockets-websocket.c -L/usr/local/lib -lwebsockets
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
window.WebSocket = window.WebSocket || window.MozWebSocket;
var websocket = new WebSocket('ws://127.0.0.1:9000',
'dumb-increment-protocol');
websocket.onopen = function () {
$('h1').css('color', 'green');
};
websocket.onerror = function () {
$('h1').css('color', 'red');
};
websocket.onmessage = function (message) {
console.log(message.data);
$('div').append($('<p>', { text: message.data }));
};
$('button').click(function(e) {
e.preventDefault();
websocket.send($('input').val());
$('input').val('');
});
});
</script>
</head>
<body>
<h1>WebSockets test</h1>
<form>
<input type="text" />
<button>Send</button>
</form>
<div></div>
</body>
</html>
#include <stdio.h>
#include <stdlib.h>
#include <libwebsockets.h>
static int callback_http(struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{
return 0;
}
static int callback_dumb_increment(struct lws *wsi,
enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: // just log message that someone is connecting
printf("connection established\n");
break;
case LWS_CALLBACK_RECEIVE: { // the funny part
// create a buffer to hold our response
// it has to have some pre and post padding. You don't need to care
// what comes there, lwss will do everything for you. For more info see
// http://git.warmcat.com/cgi-bin/cgit/lwss/tree/lib/lwss.h#n597
unsigned char *buf = (unsigned char*) malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
LWS_SEND_BUFFER_POST_PADDING);
int i;
// pointer to `void *in` holds the incomming request
// we're just going to put it in reverse order and put it in `buf` with
// correct offset. `len` holds length of the request.
for (i=0; i < len; i++) {
buf[LWS_SEND_BUFFER_PRE_PADDING + (len - 1) - i ] = ((char *) in)[i];
}
// log what we recieved and what we're going to send as a response.
// that disco syntax `%.*s` is used to print just a part of our buffer
// http://stackoverflow.com/questions/5189071/print-part-of-char-array
printf("received data: %s, replying: %.*s\n", (char *) in, (int) len,
buf + LWS_SEND_BUFFER_PRE_PADDING);
// send response
// just notice that we have to tell where exactly our response starts. That's
// why there's `buf[LWS_SEND_BUFFER_PRE_PADDING]` and how long it is.
// we know that our response has the same length as request because
// it's the same message in reverse order.
lws_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
// release memory back into the wild
free(buf);
break;
}
default:
break;
}
return 0;
}
static struct lws_protocols protocols[] = {
/* first protocol must always be HTTP handler */
{
"http-only", // name
callback_http, // callback
0 // per_session_data_size
},
{
"dumb-increment-protocol", // protocol name - very important!
callback_dumb_increment, // callback
0 // we don't use any per session data
},
{
NULL, NULL, 0 /* End of list */
}
};
int main(void) {
// server url will be http://localhost:9000
int port = 9000;
struct lws_context *context;
struct lws_context_creation_info context_info =
{
.port = port, .iface = NULL, .protocols = protocols, .extensions = NULL,
.ssl_cert_filepath = NULL, .ssl_private_key_filepath = NULL, .ssl_ca_filepath = NULL,
.gid = -1, .uid = -1, .options = 0, NULL, .ka_time = 0, .ka_probes = 0, .ka_interval = 0
};
// create lws context representing this server
context = lws_create_context(&context_info);
if (context == NULL) {
fprintf(stderr, "lws init failed\n");
return -1;
}
printf("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
while (1) {
lws_service(context, 50);
// lws_service will process all waiting events with their
// callback functions and then wait 50 ms.
// (this is a single threaded webserver and this will keep our server
// from generating load while there are not requests to process)
}
lws_context_destroy(context);
return 0;
}
@SiwonP
Copy link

SiwonP commented Apr 11, 2018

Thank you for the fork, it seems to work ! However, the Flag to compile is -lwebsockets (instead of -lwebsocket)

@vhdmsm
Copy link

vhdmsm commented Feb 7, 2019

Thank you for the fork, it seems to work ! However, the Flag to compile is -lwebsockets (instead of -lwebsocket)

That flag saved my life man!

@Momilijaz96
Copy link

Momilijaz96 commented Oct 4, 2019

server is not capable of sending message to html client!! it stays stuck at receiving LWS_CALLBACK_ESTABLISH callback and keeps printing connection established!

@avionbg
Copy link

avionbg commented Oct 18, 2019

For me its working as expected, using the latest libwebsocket / VS 2017

@Momilijaz96
Copy link

Yeah mine is fixed too!

@avionbg
Copy link

avionbg commented Oct 18, 2019

Here is a html without jQuery dependency:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
</head>

<body>
    <h1>WebSockets test</h1>
    <form>
        <input type="text" />
        <button>Send</button>
    </form>
    <div id="out"></div>
    <script type="text/javascript">
        const header = document.querySelector('h1');
        const input = document.querySelector('input');
        const button = document.querySelector('button');
        const out = document.getElementById('out');

        const WS = window.WebSocket || window.MozWebSocket;
        const websocket = new WS(
            'ws://127.0.0.1:9000', 'dumb-increment-protocol');
        websocket.onopen = function() {
            header.style.color = 'green';
        };
        websocket.onerror = function() {
            header.style.color = 'red';
        };
        websocket.onmessage = function(message) {
            console.log(message.data);
            out.insertAdjacentHTML('beforeend', `<div>${message.data}</div>`);
        };
        button.addEventListener('click', e => {
            e.preventDefault();
            websocket.send(input.value);
            input.value = '';
        });
    </script>
</body>

</html>

Copy link

ghost commented Oct 3, 2021

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment