Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
e53575bfa7 | |||
0a45b7787f | |||
b8c397e180 |
@ -115,4 +115,3 @@ set( IXWEBSOCKET_INCLUDE_DIRS
|
||||
target_include_directories( ixwebsocket PUBLIC ${IXWEBSOCKET_INCLUDE_DIRS} )
|
||||
|
||||
add_subdirectory(ws)
|
||||
add_subdirectory(examples)
|
||||
|
12
README.md
12
README.md
@ -15,7 +15,7 @@ communication channels over a single TCP connection. *IXWebSocket* is a C++ libr
|
||||
|
||||
## Examples
|
||||
|
||||
The examples folder countains a simple chat program, using a node.js broadcast server.
|
||||
The ws folder countains many interactive programs for chat and file transfers demonstrating client and server usage.
|
||||
|
||||
Here is what the client API looks like.
|
||||
|
||||
@ -144,16 +144,6 @@ Large frames are broken up into smaller chunks or messages to avoid filling up t
|
||||
* Automatic reconnection works at the TCP socket level, and will detect remote end disconnects. However, if the device/computer network become unreachable (by turning off wifi), it is quite hard to reliably and timely detect it at the socket level using `recv` and `send` error codes. [Here](https://stackoverflow.com/questions/14782143/linux-socket-how-to-detect-disconnected-network-in-a-client-program) is a good discussion on the subject. This behavior is consistent with other runtimes such as node.js. One way to detect a disconnected device with low level C code is to do a name resolution with DNS but this can be expensive. Mobile devices have good and reliable API to do that.
|
||||
* The server code is using select to detect incoming data, and creates one OS thread per connection. This isn't as scalable as strategies using epoll or kqueue.
|
||||
|
||||
## Examples
|
||||
|
||||
1. Bring up a terminal and jump to the examples folder.
|
||||
2. Compile the example C++ code. `sh build.sh`
|
||||
3. Install node.js from [here](https://nodejs.org/en/download/).
|
||||
4. Type `npm install` to install the node.js dependencies. Then `node broadcast-server.js` to run the server.
|
||||
5. Bring up a second terminal. `./cmd_websocket_chat bob`
|
||||
6. Bring up a third terminal. `./cmd_websocket_chat bill`
|
||||
7. Start typing things in any of those terminals. Hopefully you should see your message being received on the other end.
|
||||
|
||||
## C++ code organization
|
||||
|
||||
Here's a simplistic diagram which explains how the code is structured in term of class/modules.
|
||||
|
9
examples/broadcast_server/.gitignore
vendored
9
examples/broadcast_server/.gitignore
vendored
@ -1,9 +0,0 @@
|
||||
CMakeCache.txt
|
||||
package-lock.json
|
||||
CMakeFiles
|
||||
ixwebsocket_unittest
|
||||
cmake_install.cmake
|
||||
node_modules
|
||||
ixwebsocket
|
||||
Makefile
|
||||
build
|
@ -1,28 +0,0 @@
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.4.1)
|
||||
project (broadcast_server)
|
||||
|
||||
# There's -Weverything too for clang
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-32")
|
||||
|
||||
set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
|
||||
include_directories(broadcast_server .)
|
||||
|
||||
add_executable(broadcast_server
|
||||
broadcast_server.cpp)
|
||||
|
||||
if (APPLE AND USE_TLS)
|
||||
target_link_libraries(broadcast_server "-framework foundation" "-framework security")
|
||||
endif()
|
||||
|
||||
target_link_libraries(broadcast_server ixwebsocket)
|
||||
install(TARGETS broadcast_server DESTINATION bin)
|
3
examples/chat/.gitignore
vendored
3
examples/chat/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
build
|
||||
venv
|
||||
node_modules
|
@ -1,21 +0,0 @@
|
||||
#
|
||||
# cmd_websocket_chat.cpp
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.4.1)
|
||||
project (cmd_websocket_chat)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
|
||||
add_executable(cmd_websocket_chat cmd_websocket_chat.cpp)
|
||||
|
||||
if (APPLE AND USE_TLS)
|
||||
target_link_libraries(cmd_websocket_chat "-framework foundation" "-framework security")
|
||||
endif()
|
||||
|
||||
target_link_libraries(cmd_websocket_chat ixwebsocket)
|
||||
install(TARGETS cmd_websocket_chat DESTINATION bin)
|
@ -1,39 +0,0 @@
|
||||
# Building
|
||||
|
||||
1. cmake -G .
|
||||
2. make
|
||||
|
||||
## Disable TLS
|
||||
|
||||
chat$ cmake -DUSE_TLS=OFF .
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /Users/bsergeant/src/foss/ixwebsocket/examples/chat
|
||||
chat$ make
|
||||
Scanning dependencies of target ixwebsocket
|
||||
[ 16%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXSocket.cpp.o
|
||||
[ 33%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXWebSocket.cpp.o
|
||||
[ 50%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXWebSocketTransport.cpp.o
|
||||
[ 66%] Linking CXX static library libixwebsocket.a
|
||||
[ 66%] Built target ixwebsocket
|
||||
[ 83%] Linking CXX executable cmd_websocket_chat
|
||||
[100%] Built target cmd_websocket_chat
|
||||
|
||||
## Enable TLS (default)
|
||||
|
||||
```
|
||||
chat$ cmake -DUSE_TLS=ON .
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /Users/bsergeant/src/foss/ixwebsocket/examples/chat
|
||||
(venv) chat$ make
|
||||
Scanning dependencies of target ixwebsocket
|
||||
[ 14%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXSocket.cpp.o
|
||||
[ 28%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXWebSocket.cpp.o
|
||||
[ 42%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXWebSocketTransport.cpp.o
|
||||
[ 57%] Building CXX object ixwebsocket/CMakeFiles/ixwebsocket.dir/ixwebsocket/IXSocketAppleSSL.cpp.o
|
||||
[ 71%] Linking CXX static library libixwebsocket.a
|
||||
[ 71%] Built target ixwebsocket
|
||||
[ 85%] Linking CXX executable cmd_websocket_chat
|
||||
[100%] Built target cmd_websocket_chat
|
||||
```
|
@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
# 'manual' way of building. You can also use cmake.
|
||||
|
||||
g++ --std=c++11 \
|
||||
../../ixwebsocket/IXSocket.cpp \
|
||||
../../ixwebsocket/IXWebSocketTransport.cpp \
|
||||
../../ixwebsocket/IXWebSocket.cpp \
|
||||
-I ../.. \
|
||||
cmd_websocket_chat.cpp \
|
||||
-o cmd_websocket_chat
|
@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
# 'manual' way of building. You can also use cmake.
|
||||
|
||||
clang++ --std=c++11 --stdlib=libc++ \
|
||||
../../ixwebsocket/IXSocket.cpp \
|
||||
../../ixwebsocket/IXWebSocketTransport.cpp \
|
||||
../../ixwebsocket/IXSocketAppleSSL.cpp \
|
||||
../../ixwebsocket/IXWebSocket.cpp \
|
||||
cmd_websocket_chat.cpp \
|
||||
-o cmd_websocket_chat \
|
||||
-framework Security \
|
||||
-framework Foundation
|
31
examples/chat/package-lock.json
generated
31
examples/chat/package-lock.json
generated
@ -1,31 +0,0 @@
|
||||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
|
||||
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"ultron": "1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"msgpack-js": "^0.3.0",
|
||||
"ws": "^3.3.3"
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.4.1)
|
||||
project (echo_server)
|
||||
|
||||
# There's -Weverything too for clang
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-32")
|
||||
|
||||
set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
|
||||
include_directories(echo_server .)
|
||||
|
||||
add_executable(echo_server
|
||||
echo_server.cpp)
|
||||
|
||||
if (APPLE AND USE_TLS)
|
||||
target_link_libraries(echo_server "-framework foundation" "-framework security")
|
||||
endif()
|
||||
|
||||
target_link_libraries(echo_server ixwebsocket)
|
||||
install(TARGETS echo_server DESTINATION bin)
|
3
examples/ws_connect/.gitignore
vendored
3
examples/ws_connect/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
build
|
||||
venv
|
||||
node_modules
|
@ -1,20 +0,0 @@
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.4.1)
|
||||
project (ws_connect)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
|
||||
add_executable(ws_connect ws_connect.cpp)
|
||||
|
||||
if (APPLE AND USE_TLS)
|
||||
target_link_libraries(ws_connect "-framework foundation" "-framework security")
|
||||
endif()
|
||||
|
||||
target_link_libraries(ws_connect ixwebsocket)
|
||||
install(TARGETS ws_connect DESTINATION bin)
|
@ -1,11 +0,0 @@
|
||||
# Building
|
||||
|
||||
1. mkdir build
|
||||
2. cd build
|
||||
3. cmake ..
|
||||
4. make
|
||||
|
||||
## Disable TLS
|
||||
|
||||
* Enable: `cmake -DUSE_TLS=OFF ..`
|
||||
* Disable: `cmake -DUSE_TLS=ON ..`
|
@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
# 'manual' way of building. You can also use cmake.
|
||||
|
||||
g++ --std=c++11 \
|
||||
-DIXWEBSOCKET_USE_TLS \
|
||||
-g \
|
||||
../../ixwebsocket/IXEventFd.cpp \
|
||||
../../ixwebsocket/IXSocket.cpp \
|
||||
../../ixwebsocket/IXSetThreadName.cpp \
|
||||
../../ixwebsocket/IXWebSocketTransport.cpp \
|
||||
../../ixwebsocket/IXWebSocket.cpp \
|
||||
../../ixwebsocket/IXDNSLookup.cpp \
|
||||
../../ixwebsocket/IXSocketConnect.cpp \
|
||||
../../ixwebsocket/IXSocketOpenSSL.cpp \
|
||||
../../ixwebsocket/IXWebSocketPerMessageDeflate.cpp \
|
||||
../../ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp \
|
||||
-I ../.. \
|
||||
ws_connect.cpp \
|
||||
-o ws_connect \
|
||||
-lcrypto -lssl -lz -lpthread
|
4
makefile
4
makefile
@ -1,10 +1,10 @@
|
||||
#
|
||||
# This makefile is just used to easily work with docker (linux build)
|
||||
#
|
||||
all: run
|
||||
all: brew
|
||||
|
||||
brew:
|
||||
mkdir -p ws/build && (cd ws/build ; cmake .. ; make)
|
||||
mkdir -p build && (cd build ; cmake .. ; make)
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
|
@ -14,6 +14,7 @@ set (CMAKE_CXX_STANDARD 14)
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
|
||||
include_directories(ws .)
|
||||
include_directories(ws ..)
|
||||
include_directories(ws ../third_party)
|
||||
|
||||
add_executable(ws
|
||||
@ -22,6 +23,8 @@ add_executable(ws
|
||||
ixcrypto/IXHash.cpp
|
||||
ixcrypto/IXUuid.cpp
|
||||
|
||||
ws_chat.cpp
|
||||
ws_connect.cpp
|
||||
ws_transfer.cpp
|
||||
ws_send.cpp
|
||||
ws_receive.cpp
|
||||
|
@ -28,6 +28,8 @@ g++ --std=c++14 \
|
||||
ixcrypto/IXBase64.cpp \
|
||||
ixcrypto/IXHash.cpp \
|
||||
ixcrypto/IXUuid.cpp \
|
||||
ws_chat.cpp \
|
||||
ws_connect.cpp \
|
||||
ws_transfer.cpp \
|
||||
ws_send.cpp \
|
||||
ws_receive.cpp \
|
||||
|
25
ws/ws.cpp
25
ws/ws.cpp
@ -16,12 +16,17 @@
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int ws_chat_main(const std::string& url,
|
||||
const std::string& user);
|
||||
|
||||
int ws_connect_main(const std::string& url);
|
||||
|
||||
int ws_receive_main(const std::string& url,
|
||||
bool enablePerMessageDeflate);
|
||||
|
||||
extern int ws_transfer_main(int port);
|
||||
int ws_transfer_main(int port);
|
||||
|
||||
extern int ws_send_main(const std::string& url,
|
||||
int ws_send_main(const std::string& url,
|
||||
const std::string& path);
|
||||
}
|
||||
|
||||
@ -32,6 +37,7 @@ int main(int argc, char** argv)
|
||||
|
||||
std::string url;
|
||||
std::string path;
|
||||
std::string user;
|
||||
int port = 8080;
|
||||
|
||||
CLI::App* sendApp = app.add_subcommand("send", "Send a file");
|
||||
@ -44,6 +50,13 @@ int main(int argc, char** argv)
|
||||
CLI::App* transferApp = app.add_subcommand("transfer", "Broadcasting server");
|
||||
transferApp->add_option("--port", port, "Connection url");
|
||||
|
||||
CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server");
|
||||
connectApp->add_option("url", url, "Connection url")->required();
|
||||
|
||||
CLI::App* chatApp = app.add_subcommand("chat", "Group chat");
|
||||
chatApp->add_option("url", url, "Connection url")->required();
|
||||
chatApp->add_option("user", user, "User name")->required();
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
if (app.got_subcommand("transfer"))
|
||||
@ -59,6 +72,14 @@ int main(int argc, char** argv)
|
||||
bool enablePerMessageDeflate = false;
|
||||
return ix::ws_receive_main(url, enablePerMessageDeflate);
|
||||
}
|
||||
else if (app.got_subcommand("connect"))
|
||||
{
|
||||
return ix::ws_connect_main(url);
|
||||
}
|
||||
else if (app.got_subcommand("chat"))
|
||||
{
|
||||
return ix::ws_chat_main(url, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* cmd_websocket_chat.cpp
|
||||
* ws_chat.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
//
|
||||
@ -20,19 +20,13 @@
|
||||
// for convenience
|
||||
using json = nlohmann::json;
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace
|
||||
namespace ix
|
||||
{
|
||||
void log(const std::string& msg)
|
||||
{
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
class WebSocketChat
|
||||
{
|
||||
public:
|
||||
WebSocketChat(const std::string& user);
|
||||
WebSocketChat(const std::string& url,
|
||||
const std::string& user);
|
||||
|
||||
void subscribe(const std::string& channel);
|
||||
void start();
|
||||
@ -46,19 +40,27 @@ namespace
|
||||
std::pair<std::string, std::string> decodeMessage(const std::string& str);
|
||||
|
||||
private:
|
||||
std::string _url;
|
||||
std::string _user;
|
||||
|
||||
ix::WebSocket _webSocket;
|
||||
|
||||
std::queue<std::string> _receivedQueue;
|
||||
|
||||
void log(const std::string& msg);
|
||||
};
|
||||
|
||||
WebSocketChat::WebSocketChat(const std::string& user) :
|
||||
WebSocketChat::WebSocketChat(const std::string& url,
|
||||
const std::string& user) :
|
||||
_url(url),
|
||||
_user(user)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void WebSocketChat::log(const std::string& msg)
|
||||
{
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
size_t WebSocketChat::getReceivedMessagesCount() const
|
||||
{
|
||||
return _receivedQueue.size();
|
||||
@ -76,11 +78,10 @@ namespace
|
||||
|
||||
void WebSocketChat::start()
|
||||
{
|
||||
std::string url("ws://localhost:8080/");
|
||||
_webSocket.setUrl(url);
|
||||
_webSocket.setUrl(_url);
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
log(std::string("Connecting to url: ") + _url);
|
||||
|
||||
_webSocket.setOnMessageCallback(
|
||||
[this](ix::WebSocketMessageType messageType,
|
||||
@ -164,10 +165,11 @@ namespace
|
||||
_webSocket.send(encodeMessage(text));
|
||||
}
|
||||
|
||||
void interactiveMain(const std::string& user)
|
||||
void interactiveMain(const std::string& url,
|
||||
const std::string& user)
|
||||
{
|
||||
std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
|
||||
WebSocketChat webSocketChat(user);
|
||||
WebSocketChat webSocketChat(url, user);
|
||||
webSocketChat.start();
|
||||
|
||||
while (true)
|
||||
@ -187,17 +189,13 @@ namespace
|
||||
std::cout << std::endl;
|
||||
webSocketChat.stop();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int ws_chat_main(const std::string& url,
|
||||
const std::string& user)
|
||||
{
|
||||
std::string user("user");
|
||||
if (argc == 2)
|
||||
{
|
||||
user = argv[1];
|
||||
}
|
||||
|
||||
Socket::init();
|
||||
interactiveMain(user);
|
||||
interactiveMain(url, user);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,8 @@
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace
|
||||
namespace ix
|
||||
{
|
||||
void log(const std::string& msg)
|
||||
{
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
class WebSocketConnect
|
||||
{
|
||||
public:
|
||||
@ -32,6 +25,8 @@ namespace
|
||||
private:
|
||||
std::string _url;
|
||||
ix::WebSocket _webSocket;
|
||||
|
||||
void log(const std::string& msg);
|
||||
};
|
||||
|
||||
WebSocketConnect::WebSocketConnect(const std::string& url) :
|
||||
@ -40,6 +35,11 @@ namespace
|
||||
;
|
||||
}
|
||||
|
||||
void WebSocketConnect::log(const std::string& msg)
|
||||
{
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
void WebSocketConnect::stop()
|
||||
{
|
||||
_webSocket.stop();
|
||||
@ -148,18 +148,12 @@ namespace
|
||||
std::cout << std::endl;
|
||||
webSocketChat.stop();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int ws_connect_main(const std::string& url)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cerr << "Usage: ws_connect <url>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::string url = argv[1];
|
||||
|
||||
Socket::init();
|
||||
interactiveMain(url);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user