This repository has been archived by the owner on Nov 5, 2023. It is now read-only.
forked from Blizzard/civetweb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request civetweb#1059 from minhanghuang/linux-ws-cpp
Add websocket server cpp example
- Loading branch information
Showing
3 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
cmake_minimum_required(VERSION 3.5.1) | ||
project(linux_ws_server) | ||
|
||
set(TARGET_NAME ${PROJECT_NAME}) | ||
set(CMAKE_CXX_STANDARD 14) | ||
|
||
find_package(PkgConfig REQUIRED) | ||
find_package(civetweb) | ||
|
||
|
||
include_directories( | ||
${civetweb_INCLUDE_DIR} | ||
) | ||
|
||
link_directories ( | ||
/usr/local/lib | ||
) | ||
|
||
add_executable(${TARGET_NAME} main.cc) | ||
|
||
target_link_libraries(${TARGET_NAME} | ||
libcivetweb-cpp.so | ||
libcivetweb.so | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[TOC] | ||
|
||
# Civetweb websocket cpp | ||
|
||
## #1 Installation | ||
|
||
```shell | ||
git clone https://github.com/civetweb/civetweb.git | ||
mkdir buildx && cd buildx | ||
cmake -DBUILD_SHARED_LIBS=ON -DCIVETWEB_ENABLE_WEBSOCKETS=ON -DCIVETWEB_ENABLE_CXX=ON .. | ||
make | ||
sudo make install | ||
``` | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#include <iostream> | ||
#include <memory> | ||
#include <mutex> | ||
#include <sstream> | ||
#include <unistd.h> | ||
#include <unordered_map> | ||
|
||
#include "CivetServer.h" | ||
|
||
class WebSocketBase : public CivetWebSocketHandler | ||
{ | ||
|
||
public: | ||
explicit WebSocketBase(std::string name) : name_(std::move(name)) | ||
{ | ||
} | ||
|
||
bool | ||
handleConnection(CivetServer *server, const mg_connection *conn) override | ||
{ | ||
return true; | ||
} | ||
|
||
void | ||
handleReadyState(CivetServer *server, mg_connection *conn) override | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
pool_.emplace(conn, std::make_shared<std::mutex>()); | ||
} | ||
|
||
bool | ||
handleData(CivetServer *server, | ||
mg_connection *conn, | ||
int bits, | ||
char *data, | ||
size_t data_len) override | ||
{ | ||
|
||
if ((bits & 0x0F) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE) { | ||
return false; | ||
} | ||
data_.write(data, data_len); | ||
if (current_opcode_ == 0x00) { | ||
current_opcode_ = bits & 0x7f; | ||
} | ||
bool is_final_fragment = bits & 0x80; | ||
if (is_final_fragment) { | ||
switch (current_opcode_) { | ||
case MG_WEBSOCKET_OPCODE_TEXT: | ||
std::cout << data_.str() << std::endl; // print request data | ||
break; | ||
default: | ||
break; | ||
} | ||
current_opcode_ = 0x00; | ||
this->sendData(conn, data_.str()); // response | ||
data_.clear(); | ||
data_.str(std::string()); | ||
} | ||
return true; | ||
} | ||
|
||
void | ||
handleClose(CivetServer *server, const mg_connection *conn) override | ||
{ | ||
auto *connection = const_cast<mg_connection *>(conn); | ||
std::shared_ptr<std::mutex> user_lock; | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
user_lock = pool_[connection]; | ||
} | ||
{ | ||
std::unique_lock<std::mutex> lock_connection(*user_lock); | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
pool_.erase(connection); | ||
} | ||
} | ||
|
||
bool | ||
sendData(mg_connection *conn, | ||
const std::string &data, | ||
bool skippable = false, | ||
int op_code = MG_WEBSOCKET_OPCODE_TEXT) | ||
{ | ||
std::shared_ptr<std::mutex> connection_lock; | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
connection_lock = pool_[conn]; | ||
} | ||
|
||
if (!connection_lock->try_lock()) { | ||
if (skippable) { | ||
return false; | ||
} | ||
connection_lock->lock(); | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
} | ||
|
||
int ret = mg_websocket_write(conn, op_code, data.c_str(), data.size()); | ||
connection_lock->unlock(); | ||
|
||
if (ret != static_cast<int>(data.size())) { | ||
if (data.empty() && ret == 2) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
thread_local static std::stringstream data_; | ||
thread_local static unsigned char current_opcode_; | ||
|
||
private: | ||
const std::string name_; | ||
mutable std::mutex mutex_; | ||
std::unordered_map<mg_connection *, std::shared_ptr<std::mutex>> pool_; | ||
}; | ||
|
||
thread_local unsigned char WebSocketBase::current_opcode_ = 0x00; | ||
thread_local std::stringstream WebSocketBase::data_; | ||
|
||
int | ||
main() | ||
{ | ||
std::cout << "Hello, Civetweb Websocket port:8080!" << std::endl; | ||
|
||
mg_init_library(0); | ||
std::vector<std::string> options = { | ||
"document_root", | ||
".", | ||
"listening_ports", | ||
"8080", | ||
"access_control_allow_headers", | ||
"*", | ||
"access_control_allow_methods", | ||
"*", | ||
"access_control_allow_origin", | ||
"*", | ||
}; | ||
auto server = std::make_shared<CivetServer>(options); | ||
auto ws = std::make_shared<WebSocketBase>("simple"); | ||
server->addWebSocketHandler("/ws", *ws); | ||
while (true) { | ||
sleep(1); | ||
} | ||
server->close(); | ||
return 0; | ||
} |