libwebsockets: Simple WebSocket server
2016-05-04 09:08
776 查看
http://usualcarrot.com/libwebsockets-simple-websocket-server
if you're trying to use libwebsockets you probably want to build your own awesome WebSocket
server.
I've already made a tutorial on how to make a web server using libwebsocket and finally now I'm going
to make a very simple WebSocket server. At first, I wanted to make just a "port" of my previous
tutorial on Node.js but this would be I think much more complicated and I wanted to keep this as simple as possible.
But still I recommend you to read the first tutorial about building a web server because there are
some insight of how does libwebsocket work and it'll be easier to understand what's going on here.
BTW, if you're looking for some more in-depth information on how WebSockets work I recommend this article Websockets
101.
So, to keep it very simple our WebSocket server will just respond to every request you send it reverse order. For example if we send "Hello, world!" it will respond "!dlrow ,olleH".
The first part is very similar to the web server, but since we don't want to handle any HTTP requests the
stay empty.
The interesting part comes now. We need to handle each request send a response.
I tried to comment the source code where I think it's appropriate. The most important method is `libwebsocket_write` and the way it send response back to the client.
Also `void *in` and `size_t len` which holds the request and its length respectively are worth mentioning.
In the next part we define all protocols we're using. The first protocol has to be HTTP, then we can put whatever we want. Pay attention to the WebSocket protocol name.
The W3C official WebSocket definition says that
takes two arguments. WebSocket server URL and some optional protocol name (or subprotocol if you want). I didn't know what is the second argument for until I started using libwebsockets. For us the protocol name is
we'll use it later in the JavaScript part.
The rest is the same like in the web server tutorial.
At this moment you can compile and run the server (see compiling tutorial). You should
see something like this:
Now it's finally time to write some JavaScript. In order to keep it very simple I'm putting everything in one HTML file:
I think it's obvious what it does and why. The most surprising part is probably:
where
If you think about it, it means that one WebSocket server can run infinite number of different WebSocket protocols absolutely independent on each other on the same port. Well, that's interesting to me.
Now open the
like in the image bellow. Write some clever message in the input field and hit Enter. Our WebSocket server takes your message and sends it back. Also you should see log messages in the server's console too.
Complete source codes are as usually on gist.github.com, feel free to send pull requests if you find a bug or
of you have an idea how to make it even better!
So that's all for now. I believe it wasn't that horrible. I'll try to rewrite the Node.js &
WebSocket - Simple chat tutorial and put online some demo to proof that it really works :).
By the way, if you use libwebsockets for some real application say thank you tohttp://warmcat.com who created it.
One more thing, I discovered that there's a forked version of libwebsockets with some additional features.
I haven't tested it yet, but I will as soon as I can and I'll update this article with more info.
if you're trying to use libwebsockets you probably want to build your own awesome WebSocket
server.
I've already made a tutorial on how to make a web server using libwebsocket and finally now I'm going
to make a very simple WebSocket server. At first, I wanted to make just a "port" of my previous
tutorial on Node.js but this would be I think much more complicated and I wanted to keep this as simple as possible.
But still I recommend you to read the first tutorial about building a web server because there are
some insight of how does libwebsocket work and it'll be easier to understand what's going on here.
BTW, if you're looking for some more in-depth information on how WebSockets work I recommend this article Websockets
101.
So, to keep it very simple our WebSocket server will just respond to every request you send it reverse order. For example if we send "Hello, world!" it will respond "!dlrow ,olleH".
WebSocket server
The first part is very similar to the web server, but since we don't want to handle any HTTP requests the callback_httpmay be
stay empty.
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #include <stdlib.h> #include <libwebsockets.h> static int callback_http(structlibwebsocket_context * this, structlibwebsocket *wsi, enumlibwebsocket_callback_reasons reason, void *user, void *in, size_t len) { return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 | static int callback_dumb_increment(struct libwebsocket_context * this, struct libwebsocket *wsi, enum libwebsocket_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, libwebsockets will do everything for you. For more info see // http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.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. libwebsocket_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; } |
Also `void *in` and `size_t len` which holds the request and its length respectively are worth mentioning.
In the next part we define all protocols we're using. The first protocol has to be HTTP, then we can put whatever we want. Pay attention to the WebSocket protocol name.
1 2 3 4 5 6 7 8 9 10 11 12 | static struct libwebsocket_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 */ } }; |
WebSocketconstructor
takes two arguments. WebSocket server URL and some optional protocol name (or subprotocol if you want). I didn't know what is the second argument for until I started using libwebsockets. For us the protocol name is
dumb-increment-protocoland
we'll use it later in the JavaScript part.
The rest is the same like in the web server tutorial.
1 2 3 4 5 6 7 8 9 10 11 12 | int main(void) { // server url will be http://localhost:9000 int port = 9000; const char *interface = NULL; struct libwebsocket_context *context; // we're not using ssl const char *cert_path = NULL; const char *key_path = NULL; // no special options int opts = 0; // create libwebsocket context representing this server context = libwebsocket_create_context(port, interface, protocols, libwebsocket_internal_extensions, cert_path, key_path, -1, -1, opts); if (context == NULL) { fprintf(stderr, "libwebsocket init failed\n"); return -1; } printf("starting server...\n"); // infinite loop, to end this server send SIGTERM. (CTRL+C) while (1) { libwebsocket_service(context, 50); // libwebsocket_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) } libwebsocket_context_destroy(context); return 0; } |
see something like this:
Compiled without SSL support, serving unencrypted Listening on port 9000 starting server...
Frontend
Now it's finally time to write some JavaScript. In order to keep it very simple I'm putting everything in one HTML file:I think it's obvious what it does and why. The most surprising part is probably:
new WebSocket('ws://127.0.0.1:9000', 'dumb-increment-protocol');
where
dumb-increment-protocolis the subprotocol name that we specified in
static struct libwebsocket_protocols protocols[] = { … }.
If you think about it, it means that one WebSocket server can run infinite number of different WebSocket protocols absolutely independent on each other on the same port. Well, that's interesting to me.
Now open the
index.htmland if connection to our WebSocket server was successful you should see green heading "WebSocket test"
like in the image bellow. Write some clever message in the input field and hit Enter. Our WebSocket server takes your message and sends it back. Also you should see log messages in the server's console too.
Complete source codes are as usually on gist.github.com, feel free to send pull requests if you find a bug or
of you have an idea how to make it even better!
Conclusion
So that's all for now. I believe it wasn't that horrible. I'll try to rewrite the Node.js &WebSocket - Simple chat tutorial and put online some demo to proof that it really works :).
By the way, if you use libwebsockets for some real application say thank you tohttp://warmcat.com who created it.
One more thing, I discovered that there's a forked version of libwebsockets with some additional features.
I haven't tested it yet, but I will as soon as I can and I'll update this article with more info.
相关文章推荐
- Android中如何避免ANR
- Ross B. Girshick URL
- 正则表达式和数组
- PHP中二维数组去除重复项小记——可以类比php其他处理二维数组_排序,转换,去空白等等
- HTML, HTTP,web综合问题
- 时间管理 - 知道碎石怎样来的吗?它是石块破碎而成的
- 背景建模与前景检测3(Background Generation And Foreground Detection Phase 3)
- Scrum 项目1.0 2.0 3.0 4.0 5.0 6.0 7.0
- 闲话:远离百度,整理一下常用的医药搜索渠道
- 【C语言】输入一个整数N,求N以内的素数之和
- zabbix 安装
- 《java入门第一季》之面向对象(private关键字与封装概念的初探)
- 《java入门第一季》之面向对象(private关键字与封装概念的初探)
- c语言函数可变参数 例
- 背景建模与前景检测2(Background Generation And Foreground Detection Phase 2)
- view,视图组件
- android 打开新窗口
- Cognos测试数据源XQE-JDB-0004错误的解决方案
- recursive
- 背景建模与前景检测1(Background Generation And Foreground Detection)