mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-10 16:31:44 +00:00
Added pubsub example
This commit is contained in:
1 parent
870ca615de
commit
c583913290
2 files changed
+190
No files matched your search
@@ -0,0 +1,98 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>WebSocket Test</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
background-color: #cde; margin: 0;
|
||||||
|
padding: 0; font: 14px Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
div.content {
|
||||||
|
width: 800px; margin: 2em auto; padding: 20px 50px;
|
||||||
|
background-color: #fff; border-radius: 1em;
|
||||||
|
}
|
||||||
|
#messages {
|
||||||
|
border: 2px solid #fec; border-radius: 1em;
|
||||||
|
height: 10em; overflow: scroll; padding: 0.5em 1em;
|
||||||
|
}
|
||||||
|
a:link, a:visited { color: #69c; text-decoration: none; }
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
body { background-color: #fff; }
|
||||||
|
div.content {
|
||||||
|
width: auto; margin: 0 auto; border-radius: 0;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script language="javascript" type="text/javascript">
|
||||||
|
|
||||||
|
var rooms = [];
|
||||||
|
var ws = new WebSocket('ws://' + location.host + '/ws');
|
||||||
|
|
||||||
|
if (!window.console) { window.console = { log: function() {} } };
|
||||||
|
|
||||||
|
ws.onopen = function(ev) { console.log(ev); };
|
||||||
|
ws.onerror = function(ev) { console.log(ev); };
|
||||||
|
ws.onclose = function(ev) { console.log(ev); };
|
||||||
|
ws.onmessage = function(ev) {
|
||||||
|
console.log(ev);
|
||||||
|
var m = (ev.data || '').match(/^(\S+) (.+)/);
|
||||||
|
if (m[1] == 'id') {
|
||||||
|
document.getElementById('my_id').innerText = m[2];
|
||||||
|
} else if (m[1] == 'msg') {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.innerHTML = m[2];
|
||||||
|
document.getElementById('messages').appendChild(div);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
document.getElementById('send_button').onclick = function(ev) {
|
||||||
|
var msg = document.getElementById('send_input').value;
|
||||||
|
ws.send('msg ' + msg);
|
||||||
|
};
|
||||||
|
document.getElementById('room_sel').onchange = function(ev) {
|
||||||
|
var roomName = this.value || '?';
|
||||||
|
ws.send('join ' + roomName);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="content">
|
||||||
|
<h1>Websocket PubSub Demonstration</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This page demonstrates how Mongoose web server could be used to implement
|
||||||
|
<a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">
|
||||||
|
publish–subscribe pattern</a>. Open this page in several browser
|
||||||
|
windows. Each window initiates persistent
|
||||||
|
<a href="http://en.wikipedia.org/wiki/WebSocket">WebSocket</a>
|
||||||
|
connection with Mongoose, making each browser window a websocket client.
|
||||||
|
Join a room, send messages, and see messages sent by other clients.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
My ID: <b><span id="my_id"></b></span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Join room: <select id="room_sel">
|
||||||
|
<option value="">-- select room -- </option>
|
||||||
|
<option>A</option>
|
||||||
|
<option>B</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="messages">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<input type="text" id="send_input" />
|
||||||
|
<button id="send_button">Send Message</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static int s_signal_received = 0;
|
||||||
|
static struct mg_server *s_server = NULL;
|
||||||
|
|
||||||
|
// Data associated with each websocket connection
|
||||||
|
struct conn_data {
|
||||||
|
int room;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void signal_handler(int sig_num) {
|
||||||
|
signal(sig_num, signal_handler); // Reinstantiate signal handler
|
||||||
|
s_signal_received = sig_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int iterate_callback(struct mg_connection *c, enum mg_event ev) {
|
||||||
|
if (ev == MG_POLL && c->is_websocket) {
|
||||||
|
char buf[20];
|
||||||
|
int len = snprintf(buf, sizeof(buf), "%lu",
|
||||||
|
(unsigned long) * (time_t *) c->callback_param);
|
||||||
|
mg_websocket_write(c, 1, buf, len);
|
||||||
|
}
|
||||||
|
return MG_TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void handle_websocket_message(struct mg_connection *conn) {
|
||||||
|
struct conn_data *d = (struct conn_data *) conn->connection_param;
|
||||||
|
struct mg_connection *c;
|
||||||
|
|
||||||
|
printf("[%.*s]\n", (int) conn->content_len, conn->content);
|
||||||
|
if (conn->content_len > 5 && !memcmp(conn->content, "join ", 5)) {
|
||||||
|
// Client joined new room
|
||||||
|
d->room = conn->content[5];
|
||||||
|
} else if (conn->content_len > 4 && !memcmp(conn->content, "msg ", 4) &&
|
||||||
|
d->room != 0 && d->room != '?') {
|
||||||
|
// Client has sent a message. Push this message to all clients
|
||||||
|
// that are subscribed to the same room as client
|
||||||
|
for (c = mg_next(s_server, NULL); c != NULL; c = mg_next(s_server, c)) {
|
||||||
|
struct conn_data *d2 = (struct conn_data *) c->connection_param;
|
||||||
|
if (!c->is_websocket || d2->room != d->room) continue;
|
||||||
|
mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, "msg %c %p %.*s",
|
||||||
|
(char) d->room, conn,
|
||||||
|
conn->content_len - 4, conn->content + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||||
|
switch (ev) {
|
||||||
|
case MG_REQUEST:
|
||||||
|
if (conn->is_websocket) {
|
||||||
|
handle_websocket_message(conn);
|
||||||
|
return MG_TRUE;
|
||||||
|
} else {
|
||||||
|
mg_send_file(conn, "pubsub.html"); // Return MG_MORE after mg_send_file()
|
||||||
|
return MG_MORE;
|
||||||
|
}
|
||||||
|
case MG_WS_CONNECT:
|
||||||
|
// New websocket connection. Send connection ID back to the client.
|
||||||
|
conn->connection_param = calloc(1, sizeof(struct conn_data));
|
||||||
|
mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "id %p", conn);
|
||||||
|
return MG_FALSE;
|
||||||
|
case MG_CLOSE:
|
||||||
|
free(conn->connection_param);
|
||||||
|
return MG_TRUE;
|
||||||
|
case MG_AUTH:
|
||||||
|
return MG_TRUE;
|
||||||
|
default:
|
||||||
|
return MG_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
s_server = mg_create_server(NULL, ev_handler);
|
||||||
|
mg_set_option(s_server, "listening_port", "8080");
|
||||||
|
|
||||||
|
signal(SIGTERM, signal_handler);
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
|
printf("Started on port %s\n", mg_get_option(s_server, "listening_port"));
|
||||||
|
while (s_signal_received == 0) {
|
||||||
|
mg_poll_server(s_server, 100);
|
||||||
|
}
|
||||||
|
mg_destroy_server(&s_server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user