Adds concurrent_server example

This commit is contained in:
Peter Thorson
2012-02-03 09:26:08 -06:00
parent 5065ff2615
commit 8271525d4b
4 changed files with 385 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
BOOST_LIB_PATH ?= /usr/local/lib
BOOST_INCLUDE_PATH ?= /usr/local/include
CPP11 ?=
CFLAGS = -O2 $(CPP11) -I$(BOOST_INCLUDE_PATH)
LDFLAGS = -L$(BOOST_LIB_PATH)
CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_program_options -lboost_thread -lpthread -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) ../../libwebsocketpp.a $(BOOST_LIB_PATH)/libboost_system.a $(BOOST_LIB_PATH)/libboost_date_time.a $(BOOST_LIB_PATH)/libboost_regex.a $(BOOST_LIB_PATH)/libboost_thread.a -lpthread
endif
concurrent_server: concurrent_server.o
$(CXX) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CFLAGS) -o $@ $^
# cleanup by removing generated files
#
.PHONY: clean
clean:
rm -f *.o concurrent_server

View File

@@ -0,0 +1,94 @@
<!doctype html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
var ws;
var url;
function connect() {
url = document.getElementById("server_url").value;
console.log(url);
if ("WebSocket" in window) {
ws = new WebSocket(url);
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
} else {
document.getElementById("messages").innerHTML += "This Browser does not support WebSockets<br />";
return;
}
ws.onopen = function(e) {
document.getElementById("messages").innerHTML += "Client: A connection to "+ws.URL+" has been opened.<br />";
document.getElementById("server_url").disabled = true;
document.getElementById("toggle_connect").innerHTML = "Disconnect";
};
ws.onerror = function(e) {
document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.<br />";
console.log(e);
};
ws.onclose = function(e) {
document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed.<br />";
};
ws.onmessage = function(e) {
document.getElementById("messages").innerHTML += "Server: "+e.data+"<br />";
};
}
function disconnect() {
ws.close();
document.getElementById("server_url").disabled = false;
document.getElementById("toggle_connect").innerHTML = "Connect";
}
function toggle_connect() {
if (document.getElementById("server_url").disabled === false) {
connect();
} else {
disconnect();
}
}
function send() {
if (ws === undefined || ws.readyState != 1) {
document.getElementById("messages").innerHTML += "Client: Websocket is not avaliable for writing<br />";
return;
}
ws.send(document.getElementById("msg").value);
document.getElementById("msg").value = "";
}
</script>
<style>
body,html {
margin: 0px;
padding: 0px;
}
#controls {
float:right;
background-color: #999;
}
</style>
<div id="controls">
<div id="server">
<input type="text" name="server_url" id="server_url" value="ws://localhost:5000" />
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
</div>
<div id="message_input"><input type="text" name="msg" id="msg" value="Hello World!" />
<button onclick="send();">Send</button></div>
</div>
<div id="messages"></div>
</body>
</html>

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../../src/websocketpp.hpp"
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <cstring>
using websocketpp::server;
struct request {
server::handler::connection_ptr con;
int value;
};
class request_coordinator {
public:
void add_request(const request& r) {
boost::unique_lock<boost::mutex> lock(m_lock);
m_requests.push(r);
lock.unlock();
m_cond.notify_one();
}
void get_request(request& value) {
boost::unique_lock<boost::mutex> lock(m_lock);
while (m_requests.empty()) {
m_cond.wait(lock);
}
value = m_requests.front();
m_requests.pop();
}
private:
std::queue<request> m_requests;
boost::mutex m_lock;
boost::condition_variable m_cond;
};
class concurrent_server_handler : public server::handler {
public:
concurrent_server_handler(request_coordinator& c) : m_coordinator(c) {}
void on_message(connection_ptr con,message_ptr msg) {
int value = atoi(msg->get_payload().c_str());
if (value == 0) {
con->send("Invalid sleep value.");
} else {
request r;
r.con = con;
r.value = value;
m_coordinator.add_request(r);
}
}
private:
request_coordinator& m_coordinator;
};
void process_requests(request_coordinator* coordinator);
void process_requests(request_coordinator* coordinator) {
request r;
while (1) {
coordinator->get_request(r);
std::stringstream response;
response << "Sleeping for " << r.value << " milliseconds!";
r.con->send(response.str());
boost::this_thread::sleep(boost::posix_time::milliseconds(r.value));
response.str("");
response << "Done sleeping for " << r.value << " milliseconds!";
r.con->send(response.str());
}
}
int main(int argc, char* argv[]) {
unsigned short port = 9002;
if (argc == 2) {
port = atoi(argv[1]);
if (port == 0) {
std::cout << "Unable to parse port input " << argv[1] << std::endl;
return 1;
}
}
try {
request_coordinator rc;
server::handler::ptr h(new concurrent_server_handler(rc));
server echo_endpoint(h);
echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
echo_endpoint.elog().set_level(websocketpp::log::elevel::ERROR);
echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
boost::thread t1(boost::bind(&process_requests, &rc));
boost::thread t2(boost::bind(&process_requests, &rc));
std::cout << "Starting WebSocket sleep server on port " << port << std::endl;
echo_endpoint.listen(port);
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}

View File

@@ -8,6 +8,14 @@
/* Begin PBXBuildFile section */
B613878F145CA61300ED9B19 /* libboost_date_time.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBE1434AF6A0029A1B1 /* libboost_date_time.dylib */; };
B61A51C914DC273F00456432 /* concurrent_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B61A51B814DC207600456432 /* concurrent_server.cpp */; };
B61A51CA14DC274F00456432 /* libwebsocketpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1C721434A8280029A1B1 /* libwebsocketpp.dylib */; };
B61A51CB14DC276300456432 /* libboost_date_time.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBE1434AF6A0029A1B1 /* libboost_date_time.dylib */; };
B61A51CC14DC276300456432 /* libboost_program_options.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6FE8CEB145A0F1900B32547 /* libboost_program_options.dylib */; };
B61A51CD14DC276300456432 /* libboost_random.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B682888C1437464A002BA48B /* libboost_random.dylib */; };
B61A51CE14DC276300456432 /* libboost_regex.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBF1434AF6A0029A1B1 /* libboost_regex.dylib */; };
B61A51CF14DC276300456432 /* libboost_system.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBC1434AE070029A1B1 /* libboost_system.dylib */; };
B61A51D014DC276300456432 /* libboost_thread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B682888E14374689002BA48B /* libboost_thread.dylib */; };
B62A5A7214775ECF005F9EB0 /* libwebsocketpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1C721434A8280029A1B1 /* libwebsocketpp.dylib */; };
B653A715148A607D004D7BD9 /* hybi_header.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B653A714148A607D004D7BD9 /* hybi_header.hpp */; };
B653A716148A607D004D7BD9 /* hybi_header.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B653A714148A607D004D7BD9 /* hybi_header.hpp */; };
@@ -118,6 +126,15 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
B61A51BD14DC271900456432 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
B66388491487D73200DDAE13 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -217,6 +234,10 @@
B61387A5145D849E00ED9B19 /* constants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = constants.hpp; path = src/http/constants.hpp; sourceTree = "<group>"; };
B61387A6145D849E00ED9B19 /* parser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = parser.hpp; path = src/http/parser.hpp; sourceTree = "<group>"; };
B61387B61462B35700ED9B19 /* logger.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = logger.hpp; path = src/logger/logger.hpp; sourceTree = "<group>"; };
B61A51B714DC207600456432 /* concurrent_client.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = concurrent_client.html; sourceTree = "<group>"; };
B61A51B814DC207600456432 /* concurrent_server.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = concurrent_server.cpp; sourceTree = "<group>"; };
B61A51B914DC207600456432 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
B61A51BF14DC271900456432 /* concurrent_server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = concurrent_server; sourceTree = BUILT_PRODUCTS_DIR; };
B62A5A511473EBB0005F9EB0 /* connection.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = connection.hpp; path = src/connection.hpp; sourceTree = "<group>"; };
B62A5A521473EBB0005F9EB0 /* endpoint.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = endpoint.hpp; path = src/endpoint.hpp; sourceTree = "<group>"; };
B62A5A561473EBE8005F9EB0 /* client.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = client.hpp; path = src/roles/client.hpp; sourceTree = "<group>"; };
@@ -326,6 +347,20 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B61A51BC14DC271900456432 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B61A51CB14DC276300456432 /* libboost_date_time.dylib in Frameworks */,
B61A51CC14DC276300456432 /* libboost_program_options.dylib in Frameworks */,
B61A51CD14DC276300456432 /* libboost_random.dylib in Frameworks */,
B61A51CE14DC276300456432 /* libboost_regex.dylib in Frameworks */,
B61A51CF14DC276300456432 /* libboost_system.dylib in Frameworks */,
B61A51D014DC276300456432 /* libboost_thread.dylib in Frameworks */,
B61A51CA14DC274F00456432 /* libwebsocketpp.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B66388481487D73200DDAE13 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -470,6 +505,17 @@
name = logger;
sourceTree = "<group>";
};
B61A51B614DC207600456432 /* concurrent_server */ = {
isa = PBXGroup;
children = (
B61A51B714DC207600456432 /* concurrent_client.html */,
B61A51B814DC207600456432 /* concurrent_server.cpp */,
B61A51B914DC207600456432 /* Makefile */,
);
name = concurrent_server;
path = examples/concurrent_server;
sourceTree = "<group>";
};
B62A5A541473EBB9005F9EB0 /* roles */ = {
isa = PBXGroup;
children = (
@@ -669,6 +715,7 @@
B6732471148FB0FC00FC2B04 /* fuzzing_client */,
B67324891491A16500FC2B04 /* broadcast_server */,
B67324A21491A7F100FC2B04 /* stress_client */,
B61A51BF14DC271900456432 /* concurrent_server */,
);
name = Products;
sourceTree = "<group>";
@@ -745,6 +792,7 @@
B6DF1CC61435ED380029A1B1 /* examples */ = {
isa = PBXGroup;
children = (
B61A51B614DC207600456432 /* concurrent_server */,
B673249A1491A50000FC2B04 /* stress_client */,
B673248114919D6600FC2B04 /* broadcast_server_tls */,
B6732469148FB0C400FC2B04 /* fuzzing_client */,
@@ -861,6 +909,23 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
B61A51BE14DC271900456432 /* concurrent_server */ = {
isa = PBXNativeTarget;
buildConfigurationList = B61A51C614DC271900456432 /* Build configuration list for PBXNativeTarget "concurrent_server" */;
buildPhases = (
B61A51BB14DC271900456432 /* Sources */,
B61A51BC14DC271900456432 /* Frameworks */,
B61A51BD14DC271900456432 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = concurrent_server;
productName = concurrent_server;
productReference = B61A51BF14DC271900456432 /* concurrent_server */;
productType = "com.apple.product-type.tool";
};
B663884A1487D73200DDAE13 /* echo_server_tls */ = {
isa = PBXNativeTarget;
buildConfigurationList = B66388521487D73300DDAE13 /* Build configuration list for PBXNativeTarget "echo_server_tls" */;
@@ -1081,11 +1146,20 @@
B6732470148FB0FC00FC2B04 /* fuzzing_client */,
B67324881491A16500FC2B04 /* broadcast_server */,
B67324A11491A7F100FC2B04 /* stress_client */,
B61A51BE14DC271900456432 /* concurrent_server */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
B61A51BB14DC271900456432 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B61A51C914DC273F00456432 /* concurrent_server.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B66388471487D73200DDAE13 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1203,6 +1277,44 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
B61A51C714DC271900456432 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
B61A51C814DC271900456432 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
B66388531487D73300DDAE13 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1659,6 +1771,14 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B61A51C614DC271900456432 /* Build configuration list for PBXNativeTarget "concurrent_server" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B61A51C714DC271900456432 /* Debug */,
B61A51C814DC271900456432 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
B66388521487D73300DDAE13 /* Build configuration list for PBXNativeTarget "echo_server_tls" */ = {
isa = XCConfigurationList;
buildConfigurations = (