Comments (18)
I have not had or heard of such an issue, so I would suspect the problem might be in your source code. If you do not figure it out, you can post a minimal example where this issue happens.
from simple-websocket-server.
Sorry, actually the issue seems like it creates a new connection on message. Is that normal behaviour? Here are prints of the pointers
Firefox stream : Streamed opened on connection 0x7f96c5f95ac0, on server 0x7ffd76bfb5f0
Chrome stream : Streamed opened on connection 0x7f96beffcac0, on server 0x7ffd76bfb5f0
Chrome message :Message received on connection 0x7f96c5f957f0, on server 0x7ffd76bfb5f0
Firefox message : Message received on connection 0x7f96bfffe7f0, on server 0x7ffd76bfb5f0
from simple-websocket-server.
Omg sorry no, the issue was with my code. Due to a shared variable.
from simple-websocket-server.
No worries, glad you figured it out.
from simple-websocket-server.
Though this is slightly related to my issue, how would one be able to recognize if a message is coming from the same computer as the onopen, or a previous onmessage? If there is a new connection for every message (is that actually supposed to happen?), it seems difficult to identify a unique source.
Is there some sort of unique identifier for the client?
from simple-websocket-server.
The connection should not close after a message is sent, the connection should be persistent until a close is called, or an error occurs.
from simple-websocket-server.
I created a really simple desktop streaming service for a hopeless lecture room at my university where I could not use a projector. The service shows how one can store connections though: https://github.com/eidheim/desktop-stream/blob/master/main.cpp
from simple-websocket-server.
I realise my confusion was because I was looking at the pointers to the connection, not the value itself. Which seems to be different. I'm running into this issue whereas lambda functions i'm using assigning in the onmessage which have a callback for send, are having their reference values reassigned each time there is a new connection.
That is, my first connection has ID 139765550680544, and the callback will initially send to that connection. But when a second connection appears eg 139765617789328, the callback for BOTH the first and second will use this ID 139765617789328.
from simple-websocket-server.
Aha! Nope, I've just realised it was my fault again. Sorry!
All my problems simply had to do with figuring out how to handle information associated with each connection, because I had just been using global objects.
Thanks for all the help!
from simple-websocket-server.
Actually, the error still seems to be appearing. I have creation a class to hold the information for each connection, inside an unordered_map, indexed with '(size_t)connection.get()'. When I receive a message I create a callback lambda expression which I pass to the class, which itself then initialises a thread with at will eventually call the callback.
Earlier I thought my function was reassigning a value to the lambda expression because I was just using one global class instead of creating a class for each connection. But it didnt fix the issue,
The lambda expression captures the connection ptr and server (by ref).
Then the issue as above happens. If I have 1 connection there is no problem. But if I add a second, the callback of the first connection starts using the id of the second connection. Its changing the captured variable. Am I misunderstanding how lambda functions work in threads?
from simple-websocket-server.
When you create a thread, make sure you capture copies of the connection objects instead of references. The references you are using might only be valid in the scope.
from simple-websocket-server.
You should maybe read up shared_ptr and memory management in C++. This is especially important when working with threads. Mostly we try to avoid this by running events in a single threaded application, like how UI libraries do it. You then also avoid mutex locks and unlocks. However, in cases where you have heavy work that needs to be done, one would pass this to a thread, but then it is important that the connection shared_ptr object is copied into the thread lambda through capturing.
from simple-websocket-server.
I'm trying to create unicast video streams for individual connections, hence the need for individual threads for each connection. It's a heavy workload. I believe I'm capturing the variables properly as well. Here's the overall code:
class MyClass {
public:
MyClass();
~MyClass();
addCallback(std::function < void (std:string data) > callback);
launch();
private:
std::function < void (std:string data) > callback;
}
MyClass::addCallback(callback){
callback = callback;
}
MyClass::launch(){
std::thread t = std::thread{ &MyFunct, callback };
t.detach();
}
int main(int argc, char* argv[]){
const int port = 8085;
auto& stream = server.endpoint["^/stream/?$"];
std::unordered_map<size_t, std::shared_ptr<MyClass>> MyClassList;
stream.onmessage = [&server, &MyClassList ](std::shared_ptr<WsServer::Connection> connection, std::shared_ptr<WsServer::Message> message) {
auto callback = [&server, connection, &MyClassList ]( std::string data) {
printf("\n\nSending through connection id %zu\n\n" (size_t)connection.get());
//This is overwritten by the last connection, ie when the thread initialised by the 1st connection calls this, the capture information is now that of the 2nd connection (if there are 2 connections)
}
MyClassList[(size_t)connection.get()].addCallBack(callback);
MyClassList[(size_t)connection.get()].launch();
}
stream.onopen= [&MyClassList ](std::shared_ptr<WsServer::Connection> connection, std::shared_ptr<WsServer::Message> message) {
MyClassList.emplace((size_t)connection.get(), std::make_shared<MyClass>(connection));
}
}
from simple-websocket-server.
Would you mind creating a complete minimal example that I can just paste into my ws_examples.cpp file? That is, just fix the above (add the needed includes as well) so that I can look how it looks in my IDE.
from simple-websocket-server.
Especially callback=callback; looks weird.
from simple-websocket-server.
I've tried setting it up with the WsClient, but the 2nd doest seem to connect.
#include "server_ws.hpp"
#include "client_ws.hpp"
#include <unordered_map>
using namespace std;
typedef SimpleWeb::SocketServer<SimpleWeb::WS> WsServer;
typedef SimpleWeb::SocketClient<SimpleWeb::WS> WsClient;
int MyFunct ( std::function < void (std::string data) > callback ){
int loop = 0;
while(true){
callback("call loop "+std::to_string(loop ++));
sleep(1);
}
}
class MyClass {
public:
MyClass();
~MyClass();
void addCallBack(std::function < void (std::string data) > callback);
void launch();
private:
std::function < void (std::string data) > _callback;
};
MyClass::MyClass(){};
MyClass::~MyClass(){};
void MyClass::addCallBack( std::function< void (std::string data) > callback){
_callback = callback;
}
void MyClass::launch(){
cout << "Server: Launching Threaded function" << endl;
std::thread t = std::thread{ &MyFunct, _callback };
t.detach();
cout << "Server: Succesfully launched thread" << endl;
}
int main() {
//WebSocket (WS)-server at port 8085 using 1 thread
WsServer server(8085, 5);
auto& stream = server.endpoint["^/stream/?$"];
std::unordered_map<size_t, std::shared_ptr<MyClass>> MyClassList;
stream.onmessage = [&server, &MyClassList ](std::shared_ptr<WsServer::Connection> connection, std::shared_ptr<WsServer::Message> message) {
auto message_str=message->string();
cout << "Server: Message received: \"" << message_str << "\" from " << (size_t)connection.get() << endl;
auto callback = [ connection ]( std::string data ) {
cout << "Server Thread received callback request for connection "<< (size_t)connection.get()<< " : "<<data<<std::endl;
//This is overwritten by the last connection, ie when the thread initialised by the 1st connection calls this, the capture information is now that of the 2nd connection (if there are 2 connections)
};
MyClassList[(size_t)connection.get()]->addCallBack(callback);
MyClassList[(size_t)connection.get()]->launch();
};
stream.onopen = [&MyClassList](std::shared_ptr<WsServer::Connection> connection) {
cout << "Server: Opened stream " << (size_t)connection.get() << endl;
MyClassList.emplace((size_t)connection.get(), std::make_shared<MyClass>());
};
thread server_thread([&server](){
//Start WS-server
server.start();
});
this_thread::sleep_for(chrono::seconds(1));
WsClient client1("localhost:8085/stream");
client1.onopen=[&client1]() {
cout << "Client1: Opened connection" << endl;
string message="Hello";
cout << "Client1: Sending message: \"" << message << "\"" << endl;
auto send_stream=make_shared<WsClient::SendStream>();
*send_stream << message;
client1.send(send_stream);
};
WsClient client2("localhost:8085/stream");
client2.onopen=[&client2]() {
cout << "Client2: Opened connection" << endl;
string message="Hello";
cout << "Client2: Sending message: \"" << message << "\"" << endl;
auto send_stream=make_shared<WsClient::SendStream>();
*send_stream << message;
client2.send(send_stream);
};
client1.start();
this_thread::sleep_for(chrono::seconds(3));
client2.start();
server_thread.join();
return 0;
}
from simple-websocket-server.
Arg, in this demo it works. It must be to do with my code somewhere then. Frustrating.
from simple-websocket-server.
Ok it is a deeper issue with my callback. Its because I'm passing it to a C function, and having trouble making it thread safe. I posted the issue here:
http://stackoverflow.com/questions/41198854/using-a-c-class-member-function-as-a-c-callback-function-thread-safe-version
from simple-websocket-server.
Related Issues (20)
- [suggest] Send/Broadcast and Text/BinaryMode HOT 1
- Standalone Asio not found - but asio.hpp is present HOT 4
- re again WssClient::start causes on_error HOT 10
- When I use Google Chrome it happend a error. HOT 3
- exception thrown in server start (boost related) HOT 4
- Connection Timeout HOT 2
- Create example on how to stream data to a client HOT 1
- Unable to compile against standalone asio HOT 1
- How to stop the server? HOT 3
- Installed but ws_examples throws an error HOT 1
- Support for the Sec-WebSocket-Protocol field HOT 3
- fatal error C1083: Cannot open include file : 'pthread.h': No such file or directory HOT 1
- Messages split among frames aren't reasembled HOT 25
- Openssl wants void* instead of char* in 0x1000115fL HOT 1
- how to initiate send message from client HOT 3
- Client request error: End of file
- Access violation exeption HOT 3
- gdiplus
- Can't use wss client HOT 5
- Integration with Simple-Web-Server HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from simple-websocket-server.