├── LICENSE ├── README.md ├── Util.cpp ├── Util.h ├── WebSocketServer.cpp ├── WebSocketServer.h └── examples ├── chatServer ├── Makefile ├── chatServer.cpp └── index.html ├── echoServer ├── Makefile ├── echoServer.cpp └── index.html └── multiPollServer ├── Makefile ├── index.html └── multiPollServer.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Jason Kruse 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * The names of its contributors may be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL JASON KRUSE BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | 26 | ********************************* 27 | 28 | Please note this is a C++ wrapper around Andy Green's libwebsockets C library. 29 | libwebsockets is licensed under the MIT license. 30 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cppWebSockets 2 | =========== 3 | 4 | A simple, lightweight c++ WebSockets server library wrapped around the popular libwebsockets c library. 5 | 6 | ### Usage 7 | 8 | Create a class that extends `WebSocketServer` and implement the following callbacks 9 | 10 | ``` 11 | void onConnect( int socketID ); // New websocket connection 12 | void onMessage( int socketID, const string& data ); // Message received from connected client 13 | void onDisconnect( int socketID ); // Client disconnect 14 | void onError( int socketID, const string& message ); // Networking error 15 | ``` 16 | 17 | Then simply instantiate your server and call `run()` 18 | 19 | ``` 20 | MyServer s = MyServer( 8080 ); // MyServer extends WebSocketServer listening on port 8080 21 | s.run( ); 22 | ``` 23 | 24 | At any arbitrary time, you can push a message to a client by calling `send( int socketID, string data )`. 25 | 26 | If your server is more complex and needs to monitor its own connections in addition to WebSocket connections, you can manage your own event loop. Instead of calling `s.run( )`, use the `s.wait( )` function. A good illustration of this is located in [examples/multiPollServer/multiPollServer.cpp](https://github.com/mnisjk/cppWebSockets/blob/master/examples/multiPollServer/multiPollServer.cpp) 27 | 28 | ### Features 29 | 30 | * Implement your own web socket server in less than 50 lines of c++. 31 | * OpenSSL support 32 | * WebSocket RFC6455 implementation 33 | * Abstracts away all c pointers and managing when sockets are writable 34 | * Push data to any client at any time 35 | * Key => Value storage for any socket with `setValue( int socketID, const string& name, const string& value );` and `getValue( int socketID, const string& name );` 36 | 37 | ### Examples 38 | 39 | Check out the [examples](https://github.com/mnisjk/cppWebSockets/blob/master/examples/) directory for fully implemented illustrations. There is a basic echo and chat server as well as a more complex server that manages multiple `poll( )` loops. They should demonstrate how easy this library is to use and serve as basic scaffolding for your projects. 40 | 41 | ### Dependencies 42 | 43 | This is built on top of [warmcat](http://warmcat.com/)'s wonderful, lightweight [libwebsocket](http://libwebsockets.org/) c library. To install: 44 | 45 | ``` 46 | mnisjk@localdev ~ $ git clone git://git.libwebsockets.org/libwebsockets 47 | mnisjk@localdev ~ $ cd libwebsockets 48 | mnisjk@localdev libwebsockets $ cmake . 49 | mnisjk@localdev libwebsockets $ make 50 | mnisjk@localdev libwebsockets $ sudo make install 51 | ``` 52 | 53 | ### Compile and run 54 | 55 | All examples have Makefiles, so simply run `make` and then run the example. When creating your own projects, your compile commands will look like the following: 56 | 57 | ``` 58 | mnisjk@localdev ~ $ g++ -w -DLOG_TO_STDOUT=1 -omyserver Util.cpp WebSocketServer.cpp myserver.cpp -lwebsockets 59 | mnisjk@localdev ~ $ ./myserver 60 | ``` 61 | -------------------------------------------------------------------------------- /Util.cpp: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * Util.cpp 3 | * 4 | * A few very basic utility functions for WebSocketServer 5 | * 6 | * Author : Jason Kruse or @mnisjk 7 | * Copyright : 2014 8 | * License : BSD (see LICENSE) 9 | * -------------------------------------------------------------------------- 10 | **/ 11 | 12 | #include 13 | #include "Util.h" 14 | 15 | using namespace std; 16 | 17 | #define LOG_PREFIX "[cppWebSockets] " 18 | 19 | void Util::log( const string& message ) 20 | { 21 | const string& logMessage = LOG_PREFIX + message; 22 | syslog( LOG_WARNING, "%s", logMessage.c_str( ) ); 23 | 24 | #ifdef LOG_TO_STDOUT 25 | printf( "%s\n", logMessage.c_str( ) ); 26 | #endif 27 | } 28 | 29 | void Util::log( const char* message ) 30 | { 31 | log( string( message ) ); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Util.h: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * Util.h 3 | * 4 | * A few very basic utility functions for WebSocketServer 5 | * 6 | * Author : Jason Kruse or @mnisjk 7 | * Copyright : 2014 8 | * License : BSD (see LICENSE) 9 | * -------------------------------------------------------------------------- 10 | **/ 11 | 12 | #ifndef _UTIL_H 13 | #define _UTIL_H 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | 22 | ///////////////////////////////////////////////////////////////////////////// 23 | ///////////////////////////////////////////////////////////////////////////// 24 | /// Util 25 | /// --------- 26 | 27 | class Util 28 | { 29 | public: 30 | static void log( const string& message ); 31 | static void log( const char* message ); 32 | template 33 | static inline string toString(T t) { stringstream s; s << t; return s.str(); } 34 | }; 35 | 36 | // Util.h 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /WebSocketServer.cpp: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * WebSocketServer.cpp 3 | * 4 | * Base class that WebSocket implementations must inherit from. Handles the 5 | * client connections and calls the child class callbacks for connection 6 | * events like onConnect, onMessage, and onDisconnect. 7 | * 8 | * Author : Jason Kruse or @mnisjk 9 | * Copyright : 2014 10 | * License : BSD (see LICENSE) 11 | * -------------------------------------------------------------------------- 12 | **/ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "libwebsockets.h" 20 | #include "Util.h" 21 | #include "WebSocketServer.h" 22 | 23 | using namespace std; 24 | 25 | // 0 for unlimited 26 | #define MAX_BUFFER_SIZE 0 27 | 28 | // Nasty hack because certain callbacks are statically defined 29 | WebSocketServer *self; 30 | 31 | static int callback_main( struct lws *wsi, 32 | enum lws_callback_reasons reason, 33 | void *user, 34 | void *in, 35 | size_t len ) 36 | { 37 | int fd; 38 | unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING]; 39 | unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING]; 40 | 41 | switch( reason ) { 42 | case LWS_CALLBACK_ESTABLISHED: 43 | self->onConnectWrapper( lws_get_socket_fd( wsi ) ); 44 | lws_callback_on_writable( wsi ); 45 | break; 46 | 47 | case LWS_CALLBACK_SERVER_WRITEABLE: 48 | fd = lws_get_socket_fd( wsi ); 49 | while( !self->connections[fd]->buffer.empty( ) ) 50 | { 51 | const char * message = self->connections[fd]->buffer.front( ); 52 | int msgLen = strlen(message); 53 | int charsSent = lws_write( wsi, (unsigned char *)message, msgLen, LWS_WRITE_TEXT ); 54 | if( charsSent < msgLen ) 55 | self->onErrorWrapper( fd, string( "Error writing to socket" ) ); 56 | else 57 | // Only pop the message if it was sent successfully. 58 | self->connections[fd]->buffer.pop_front( ); 59 | } 60 | lws_callback_on_writable( wsi ); 61 | break; 62 | 63 | case LWS_CALLBACK_RECEIVE: 64 | self->onMessage( lws_get_socket_fd( wsi ), string( (const char *)in, len ) ); 65 | break; 66 | 67 | case LWS_CALLBACK_CLOSED: 68 | self->onDisconnectWrapper( lws_get_socket_fd( wsi ) ); 69 | break; 70 | 71 | default: 72 | break; 73 | } 74 | return 0; 75 | } 76 | 77 | static struct lws_protocols protocols[] = { 78 | { 79 | "/", 80 | callback_main, 81 | 0, // user data struct not used 82 | MAX_BUFFER_SIZE, 83 | },{ NULL, NULL, 0, 0 } // terminator 84 | }; 85 | 86 | WebSocketServer::WebSocketServer( int port, const string certPath, const string& keyPath ) 87 | { 88 | this->_port = port; 89 | this->_certPath = certPath; 90 | this->_keyPath = keyPath; 91 | 92 | lws_set_log_level( 0, lwsl_emit_syslog ); // We'll do our own logging, thank you. 93 | struct lws_context_creation_info info; 94 | memset( &info, 0, sizeof info ); 95 | info.port = this->_port; 96 | info.iface = NULL; 97 | info.protocols = protocols; 98 | #ifndef LWS_NO_EXTENSIONS 99 | info.extensions = lws_get_internal_extensions( ); 100 | #endif 101 | 102 | if( !this->_certPath.empty( ) && !this->_keyPath.empty( ) ) 103 | { 104 | Util::log( "Using SSL certPath=" + this->_certPath + ". keyPath=" + this->_keyPath + "." ); 105 | info.ssl_cert_filepath = this->_certPath.c_str( ); 106 | info.ssl_private_key_filepath = this->_keyPath.c_str( ); 107 | } 108 | else 109 | { 110 | Util::log( "Not using SSL" ); 111 | info.ssl_cert_filepath = NULL; 112 | info.ssl_private_key_filepath = NULL; 113 | } 114 | info.gid = -1; 115 | info.uid = -1; 116 | info.options = 0; 117 | 118 | // keep alive 119 | info.ka_time = 60; // 60 seconds until connection is suspicious 120 | info.ka_probes = 10; // 10 probes after ^ time 121 | info.ka_interval = 10; // 10s interval for sending probes 122 | this->_context = lws_create_context( &info ); 123 | if( !this->_context ) 124 | throw "libwebsocket init failed"; 125 | Util::log( "Server started on port " + Util::toString( this->_port ) ); 126 | 127 | // Some of the libwebsocket stuff is define statically outside the class. This 128 | // allows us to call instance variables from the outside. Unfortunately this 129 | // means some attributes must be public that otherwise would be private. 130 | self = this; 131 | } 132 | 133 | WebSocketServer::~WebSocketServer( ) 134 | { 135 | // Free up some memory 136 | for( map::const_iterator it = this->connections.begin( ); it != this->connections.end( ); ++it ) 137 | { 138 | Connection* c = it->second; 139 | this->connections.erase( it->first ); 140 | delete c; 141 | } 142 | } 143 | 144 | void WebSocketServer::onConnectWrapper( int socketID ) 145 | { 146 | Connection* c = new Connection; 147 | c->createTime = time( 0 ); 148 | this->connections[ socketID ] = c; 149 | this->onConnect( socketID ); 150 | } 151 | 152 | void WebSocketServer::onDisconnectWrapper( int socketID ) 153 | { 154 | this->onDisconnect( socketID ); 155 | this->_removeConnection( socketID ); 156 | } 157 | 158 | void WebSocketServer::onErrorWrapper( int socketID, const string& message ) 159 | { 160 | Util::log( "Error: " + message + " on socketID '" + Util::toString( socketID ) + "'" ); 161 | this->onError( socketID, message ); 162 | this->_removeConnection( socketID ); 163 | } 164 | 165 | void WebSocketServer::send( int socketID, string data ) 166 | { 167 | // Push this onto the buffer. It will be written out when the socket is writable. 168 | this->connections[socketID]->buffer.push_back( data.c_str() ); 169 | } 170 | 171 | void WebSocketServer::broadcast(string data ) 172 | { 173 | for( map::const_iterator it = this->connections.begin( ); it != this->connections.end( ); ++it ) 174 | this->send( it->first, data ); 175 | } 176 | 177 | void WebSocketServer::setValue( int socketID, const string& name, const string& value ) 178 | { 179 | this->connections[socketID]->keyValueMap[name] = value; 180 | } 181 | 182 | string WebSocketServer::getValue( int socketID, const string& name ) 183 | { 184 | return this->connections[socketID]->keyValueMap[name]; 185 | } 186 | int WebSocketServer::getNumberOfConnections( ) 187 | { 188 | return this->connections.size( ); 189 | } 190 | 191 | void WebSocketServer::run( uint64_t timeout ) 192 | { 193 | while( 1 ) 194 | { 195 | this->wait( timeout ); 196 | } 197 | } 198 | 199 | void WebSocketServer::wait( uint64_t timeout ) 200 | { 201 | if( lws_service( this->_context, timeout ) < 0 ) 202 | throw "Error polling for socket activity."; 203 | } 204 | 205 | void WebSocketServer::_removeConnection( int socketID ) 206 | { 207 | Connection* c = this->connections[ socketID ]; 208 | this->connections.erase( socketID ); 209 | delete c; 210 | } 211 | -------------------------------------------------------------------------------- /WebSocketServer.h: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * WebSocketServer.h 3 | * 4 | * Base class that WebSocket implementations must inherit from. Handles the 5 | * client connections and calls the child class callbacks for connection 6 | * events like onConnect, onMessage, and onDisconnect. 7 | * 8 | * Author : Jason Kruse or @mnisjk 9 | * Copyright : 2014 10 | * License : BSD (see LICENSE) 11 | * -------------------------------------------------------------------------- 12 | **/ 13 | 14 | #ifndef _WEBSOCKETSERVER_H 15 | #define _WEBSOCKETSERVER_H 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "libwebsockets.h" 26 | 27 | using namespace std; 28 | 29 | ///////////////////////////////////////////////////////////////////////////// 30 | ///////////////////////////////////////////////////////////////////////////// 31 | /// WebSocketServer 32 | /// --------- 33 | class WebSocketServer 34 | { 35 | public: 36 | // Represents a client connection 37 | struct Connection 38 | { 39 | list buffer; // Ordered list of pending messages to flush out when socket is writable 40 | map keyValueMap; 41 | time_t createTime; 42 | }; 43 | 44 | // Manages connections. Unfortunately this is public because static callback for 45 | // libwebsockets is defined outside the instance and needs access to it. 46 | map connections; 47 | 48 | // Constructor / Destructor 49 | WebSocketServer( int port, const string certPath = "", const string& keyPath = "" ); 50 | ~WebSocketServer( ); 51 | 52 | void run( uint64_t timeout = 50 ); 53 | void wait( uint64_t timeout = 50 ); 54 | void send( int socketID, string data ); 55 | void broadcast( string data ); 56 | 57 | // Key => value storage for each connection 58 | string getValue( int socketID, const string& name ); 59 | void setValue( int socketID, const string& name, const string& value ); 60 | int getNumberOfConnections( ); 61 | 62 | // Overridden by children 63 | virtual void onConnect( int socketID ) = 0; 64 | virtual void onMessage( int socketID, const string& data ) = 0; 65 | virtual void onDisconnect( int socketID ) = 0; 66 | virtual void onError( int socketID, const string& message ) = 0; 67 | 68 | 69 | // Wrappers, so we can take care of some maintenance 70 | void onConnectWrapper( int socketID ); 71 | void onDisconnectWrapper( int socketID ); 72 | void onErrorWrapper( int socketID, const string& message ); 73 | 74 | protected: 75 | // Nothing, yet. 76 | 77 | private: 78 | int _port; 79 | string _keyPath; 80 | string _certPath; 81 | struct lws_context *_context; 82 | 83 | void _removeConnection( int socketID ); 84 | }; 85 | 86 | // WebSocketServer.h 87 | #endif 88 | -------------------------------------------------------------------------------- /examples/chatServer/Makefile: -------------------------------------------------------------------------------- 1 | hellomake: 2 | g++ -w -DLOG_TO_STDOUT=1 -ochatserver ../../Util.cpp ../../WebSocketServer.cpp chatServer.cpp -lwebsockets 3 | -------------------------------------------------------------------------------- /examples/chatServer/chatServer.cpp: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * chatServer.cpp 3 | * 4 | * A basic example of how to implement a WebSocketServer. Creats a WS server 5 | * bound to port 8080 for basic chatting. It listens for connections and 6 | * assigns them a random handle based on their socket FD. Whenever a message 7 | * is received on the server, it is sent out to all connected clients. 8 | * received, it echos the same message back to the client. 9 | * 10 | * Author : Jason Kruse or @mnisjk 11 | * Copyright : 2014 12 | * License : BSD (see LICENSE) 13 | * -------------------------------------------------------------------------- 14 | **/ 15 | 16 | // Log to stdout for easy debugging. 17 | #define LOG_TO_STDOUT 1 18 | 19 | #include "../../Util.h" 20 | #include "../../WebSocketServer.h" 21 | 22 | using namespace std; 23 | 24 | // For any real project this should be defined separately in a header file 25 | class ChatServer : public WebSocketServer 26 | { 27 | public: 28 | ChatServer( int port ); 29 | ~ChatServer( ); 30 | virtual void onConnect( int socketID ); 31 | virtual void onMessage( int socketID, const string& data ); 32 | virtual void onDisconnect( int socketID ); 33 | virtual void onError( int socketID, const string& message ); 34 | }; 35 | 36 | int main( int argc, char **argv ) 37 | { 38 | ChatServer cs = ChatServer( 8080 ); 39 | cs.run( ); 40 | } 41 | 42 | ChatServer::ChatServer( int port ) : WebSocketServer( port ) 43 | { 44 | } 45 | 46 | ChatServer::~ChatServer( ) 47 | { 48 | } 49 | 50 | 51 | void ChatServer::onConnect( int socketID ) 52 | { 53 | // Give this connection a random user ID 54 | const string& handle = "User #" + Util::toString( socketID ); 55 | Util::log( "New connection: " + handle ); 56 | 57 | // Associate this handle with the connection 58 | this->setValue( socketID, "handle", handle ); 59 | 60 | // Let everyone know the new user has connected 61 | this->broadcast( handle + " has connected." ); 62 | } 63 | 64 | void ChatServer::onMessage( int socketID, const string& data ) 65 | { 66 | // Send the received message to all connected clients in the form of 'User XX: message...' 67 | Util::log( "Received: " + data ); 68 | const string& message = this->getValue( socketID, "handle" ) + ": " + data; 69 | 70 | this->broadcast( message ); 71 | } 72 | 73 | void ChatServer::onDisconnect( int socketID ) 74 | { 75 | const string& handle = this->getValue( socketID, "handle" ); 76 | Util::log( "Disconnected: " + handle ); 77 | 78 | // Let everyone know the user has disconnected 79 | const string& message = handle + " has disconnected."; 80 | for( map::const_iterator it = this->connections.begin( ); it != this->connections.end( ); ++it ) 81 | if( it->first != socketID ) 82 | // The disconnected connection gets deleted after this function runs, so don't try to send to it 83 | // (It's still around in case the implementing class wants to perform any clean up actions) 84 | this->send( it->first, message ); 85 | } 86 | 87 | void ChatServer::onError( int socketID, const string& message ) 88 | { 89 | Util::log( "Error: " + message ); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /examples/chatServer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cppWebSockets chat server example 5 | 6 | 7 | 8 | 18 | 19 | 20 |

Basic chat server

21 |
22 |

23 | This is a super basic example of a chat server using lwebsockets++. This also 24 | shows how to use the key => value storage to associate data with a connection. 25 |

26 |

    27 |
  • Compile and run the server in examples/chatServer.
  • 28 |
  • Open this page in multiple tabs.
  • 29 |
  • Start chatting with yourself
  • 30 |
31 |


32 | Note: 33 | There is no flash fallback, so make sure you have a modern browser with 34 | WebSocket support. 35 |

36 |
37 |
38 | Demo 39 | 40 | 41 | 42 |
Server responses
43 |
44 | 45 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /examples/echoServer/Makefile: -------------------------------------------------------------------------------- 1 | hellomake: 2 | g++ -w -DLOG_TO_STDOUT=1 -oechoserver ../../Util.cpp ../../WebSocketServer.cpp echoServer.cpp -lwebsockets 3 | -------------------------------------------------------------------------------- /examples/echoServer/echoServer.cpp: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * echoServer.cpp 3 | * 4 | * A basic example of how to implement a WebSocketServer. Creats a WS server 5 | * bound to port 8080. It listens for connections, and when a message is 6 | * received, it echos the same message back to the client. 7 | * 8 | * Author : Jason Kruse or @mnisjk 9 | * Copyright : 2014 10 | * License : BSD (see LICENSE) 11 | * -------------------------------------------------------------------------- 12 | **/ 13 | 14 | // Log to stdout for easy debugging. 15 | #define LOG_TO_STDOUT 1 16 | 17 | #include "../../Util.h" 18 | #include "../../WebSocketServer.h" 19 | 20 | using namespace std; 21 | 22 | // For any real project this should be defined separately in a header file 23 | class EchoServer : public WebSocketServer 24 | { 25 | public: 26 | EchoServer( int port ); 27 | ~EchoServer( ); 28 | virtual void onConnect( int socketID ); 29 | virtual void onMessage( int socketID, const string& data ); 30 | virtual void onDisconnect( int socketID ); 31 | virtual void onError( int socketID, const string& message ); 32 | }; 33 | 34 | int main( int argc, char **argv ) 35 | { 36 | EchoServer es = EchoServer( 8080 ); 37 | es.run( ); 38 | } 39 | 40 | EchoServer::EchoServer( int port ) : WebSocketServer( port ) 41 | { 42 | } 43 | 44 | EchoServer::~EchoServer( ) 45 | { 46 | } 47 | 48 | 49 | void EchoServer::onConnect( int socketID ) 50 | { 51 | Util::log( "New connection" ); 52 | } 53 | 54 | void EchoServer::onMessage( int socketID, const string& data ) 55 | { 56 | // Reply back with the same message 57 | Util::log( "Received: " + data ); 58 | this->send( socketID, data ); 59 | } 60 | 61 | void EchoServer::onDisconnect( int socketID ) 62 | { 63 | Util::log( "Disconnect" ); 64 | } 65 | 66 | void EchoServer::onError( int socketID, const string& message ) 67 | { 68 | Util::log( "Error: " + message ); 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /examples/echoServer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cppWebSockets echo example 5 | 6 | 7 | 8 | 11 | 12 | 13 |

Send a message to the server

14 |
15 |

This is a super basic example of how to connect to the websocket server.

16 |

    17 |
  • Compile and run the server in examples/echoServer.
  • 18 |
  • 19 | Enter a message in the text box below; it will be sent to the server which 20 | will reply back with the same message. 21 |
  • 22 |
23 |


24 | Note: 25 | There is no flash fallback, so make sure you have a modern browser with 26 | WebSocket support. 27 |

28 |
29 |
30 | Demo 31 | 32 | 33 |
Server responses
34 |
35 |
36 | 37 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/multiPollServer/Makefile: -------------------------------------------------------------------------------- 1 | hellomake: 2 | g++ -w -omultipollserver ../../Util.cpp ../../WebSocketServer.cpp multiPollServer.cpp -lwebsockets 3 | -------------------------------------------------------------------------------- /examples/multiPollServer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | cppWebSockets multipoll example 5 | 6 | 7 | 8 | 11 | 12 | 13 |

Multi Poll server

14 |
15 |

16 | A basic example of how to implement a WebSocketServer and listen to other 17 | fds. 18 |


19 |

20 | This is useful when your server needs to handle connections from 21 | WebSocket clients and other TCP connections at the same time. 22 |

23 |

    24 |
  • Compile and run the server in examples/multiPollServer.
  • 25 |
  • 26 | Enter messages into standard input and they will be sent out to 27 | all connected clients. 28 |
  • 29 |
30 |


31 | Note: 32 | There is no flash fallback, so make sure you have a modern browser with 33 | WebSocket support. 34 |

35 |
36 |
37 | Demo 38 |
Server messages
39 |
40 |
41 | 42 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /examples/multiPollServer/multiPollServer.cpp: -------------------------------------------------------------------------------- 1 | /** -------------------------------------------------------------------------- 2 | * multiPollServer.cpp 3 | * 4 | * A basic example of how to implement a WebSocketServer *AND* listen to other 5 | * fds. This is useful when your server needs to handle connections from 6 | * WebSocket clients and other TCP connections at the same time. 7 | * 8 | * It also demonstrates how to send to an arbitrary WebSocket connection at 9 | * any time. 10 | * 11 | * This program listens for input on stdin and WebSockets on port 8080 12 | * simultaneously. When new data is available on stdin (line buffered), 13 | * it sends that string out to all connected WebSocket clients. 14 | * 15 | * Author : Jason Kruse or @mnisjk 16 | * Copyright : 2014 17 | * License : BSD (see LICENSE) 18 | * -------------------------------------------------------------------------- 19 | **/ 20 | 21 | #include 22 | #include 23 | #include "../../Util.h" 24 | #include "../../WebSocketServer.h" 25 | 26 | #define TIMEOUT 50 27 | #define PROMPT "message> " 28 | 29 | using namespace std; 30 | 31 | // For any real project this should be defined separately in a header file 32 | class MultiPollServer : public WebSocketServer 33 | { 34 | public: 35 | MultiPollServer( int port ); 36 | ~MultiPollServer( ); 37 | virtual void onConnect( int socketID ); 38 | virtual void onMessage( int socketID, const string& data ); 39 | virtual void onDisconnect( int socketID ); 40 | virtual void onError( int socketID, const string& message ); 41 | }; 42 | 43 | 44 | void showPrompt( ) 45 | { 46 | cout << PROMPT; 47 | fflush( stdout ); 48 | } 49 | 50 | int main( int argc, char **argv ) 51 | { 52 | // Set up the stdin polling 53 | int p; 54 | char buf[1024]; 55 | struct pollfd pfds[1]; 56 | pfds[0].fd = 0; 57 | pfds[0].events = POLLIN; 58 | 59 | // Start the WebSocket server 60 | MultiPollServer s = MultiPollServer( 8080 ); 61 | 62 | cout << "Type a message followed by enter to send to all connected clients." << endl << endl; 63 | showPrompt( ); 64 | while( 1 ) 65 | { 66 | // Handle websocket stuff 67 | s.wait( TIMEOUT ); 68 | 69 | // Handle stdin 70 | p = poll( pfds, 1, TIMEOUT ); 71 | if( p > 0 && pfds[0].revents & POLLIN ) 72 | { 73 | int len = read( 0, buf, 1024 ); 74 | if( !len ) 75 | return 0; 76 | buf[len] = 0; // make sure the c-string terminator is where we want it to be since this buf is re-used. 77 | string input = string( buf ); 78 | input.resize( input.size( ) - 1 ); // Remove the trailing \n 79 | 80 | // Send it out to WS clients. 81 | Util::log( "Sending '" + input + "' to " + Util::toString( s.getNumberOfConnections( ) ) + " client(s)." ); 82 | s.broadcast( input ); 83 | 84 | // Diplay the prompt. 85 | showPrompt( ); 86 | } 87 | } 88 | } 89 | 90 | MultiPollServer::MultiPollServer( int port ) : WebSocketServer( port ) 91 | { 92 | } 93 | 94 | MultiPollServer::~MultiPollServer( ) 95 | { 96 | } 97 | 98 | 99 | void MultiPollServer::onConnect( int socketID ) 100 | { 101 | Util::log( "New connection" ); 102 | } 103 | 104 | void MultiPollServer::onMessage( int socketID, const string& data ) 105 | { 106 | // Should never get hit. 107 | } 108 | 109 | void MultiPollServer::onDisconnect( int socketID ) 110 | { 111 | Util::log( "Disconnect" ); 112 | } 113 | 114 | void MultiPollServer::onError( int socketID, const string& message ) 115 | { 116 | Util::log( "Error: " + message ); 117 | } 118 | 119 | 120 | --------------------------------------------------------------------------------