Websocket broadcasting not working - c++

I have an issue with my websocket.
I have recently switched my server from PHP to c++ side, and used the POCO library, i used exactly this script:
WebSocketServer.cpp
For the one client side in c++ i used a snipet i found here on stackoverflow:
WebSocketClient.cpp
I modified the client a bit, first it sends a default message as soon as i connect to the server.
I wrapped the whole thing with an Update function from my main app, that I am constantly able to recieve messages:
void CLeagueStats :: Update( ) {
if(m_Connected) {
string msg = Recv( );
if(msg != "") {
//handleIncomingMsg( msg );
}
} else if(GetTime() - LastReconnectTime > 90 || LastReconnectTime == 0) {
Connect( );
}
}
string CLeagueStats :: Recv( ) {
char receiveBuff[256];
int flags=0;
int rlen=m_psock->receiveFrame(receiveBuff,256,flags);
CONSOLE_Print("Recv: "+string(receiveBuff));
return string(receiveBuff);
}
I have now written a totally simple javascript client which is initalizing on page load:
<script type="text/javascript">
var ip_port = 'localhost:9980';
var ohc;
if (typeof (MozWebSocket) == 'function')
ohc = new MozWebSocket('ws://' + ip_port);
else
ohc = new WebSocket('ws://' + ip_port);
var self = this;
setTimeout(function() {
self.ohc.send("hey");
}, 500);
</script>
The server log includes both messages:
C++ App:
WebSocket connection established. Frame received (length=5, flags=0x81).
Javascript:
WebSocket connection established. Frame received (length=3, flags=0x81).
But the log from the C++ App does send the connection message and recieve it back, but i dont get the message from the js-client:
[Websocket] Connecting to websocket.
[Websocket] Send: hello
[Websocket] Recv: hello
Why this happen?
Isn't the snippet form the servercode directly sending the message back to all clients?
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
app.logger().information(Poco::format("Frame received (length=%d, flags=0x%x).", n,unsigned(flags)));
ws.sendFrame(buffer, n, flags);
Is there anything wrong with the code?

I am not a situation to reproduce the environment but I had a similar issue using Python and IOS web sockets. Every other technology we used was working in with Python Sockets flawlessly but IOS web socket had problem. After many days later we find out that IOS web socket does not send a communication ender (EOM) that Python can process. So the we had to handle different IOS sockets different.
I have checked WebSocket flags 81 so it is text and frame is finish. But I would suggest you to check from Developer Tools of browser to see what is recieved over the socket connection from Network Tab.
I may be problem of End of Message did not understood by javascript WebSocket. If you see the data hello on developer tools then it would be easy to handle with situation. However if you don't see any message coming then the problem is most probably from C++ code.
In attachment you can see how Chrome shows the socket data transactions. Keep in mind that clicking on the connection on the left list will update the transactions they are not live.
Hope this helps you.
If not go deeper using tcpdump or similar sowftware to be sure if they really sent and got by two sides.

Related

How can i send packages on a Minecraft Client (With Fabricmc) and receive it on a Bukkit Server?

I'm a Chinese secondary school student,so my written English may not very well.
How can i send packages (like some words) on a Minecraft Client (Use a Fabricmc Mod to send) and receive it on the bukkit server on MC Multiplayer?
This is done using what's known as the 'plugin messaging channel'. Take a look at this Fabricmc wiki to read about client networking (messaging). See this Spigot wiki on the plugin server-side messaging channel; ignore that this wiki talks a lot about bungee, it's just because that's a common use case. You can make your own channel.
The code below is copied from said wikis and is very much pseudo-code:
Client
Sending from the client
PacketByteBuf buf = PacketByteBufs.create();
buf.writeBlockPos(target);
ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);
Receiving on the client
ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {
client.execute(() -> {
// Everything in this lambda is run on the render thread
ClientBlockHighlighting.highlightBlock(client, target);
});
});
Where you see TutorialNetworkingConstants.HIGHL..., that's the Identifier for the channel.
Server (Spigot/Bukkit)
Sending from the server
player.sendPluginMessage(this, "YourChannelName", out.toByteArray());
Receiving on the server
#Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals("YourChannelName")) {
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String data = in.readUTF();
...
Take a thorough read of those tutorials, they should cover all you need to know. Just be sure to unregister your channels on both the client and server.

ESP32 Arduino httpSecureClient -1 error at core 0 without reason why

I'm having an issue with the httpsecureclient library for the ESP in the Arduino IDE.
I try to send http requests to a https domain (that doesn't change) and works alot of times just fine.
Like I do some HTTP calls to obtain certain data to let the ESP do it's thing. But when I want to let the ESP post a payload to a server, using the WiFiClientSecure and HTTPClient, it sometimes works without issues, but all of a sudden, it stops working and throws me the well known, nothing saying -1 response code...
The code I ues to send a heartbeat is the following;
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
WiFiClientSecure ApiClient;
HTTPClient ApiHttpClient;
StaticJsonDocument<256> doc;
doc["mac"] = deviceMacAddress;
doc["key"] = DEVICE_SECRET;
doc["type"] = DIGITAL_HQ_SOFTWARE_TYPE;
String heartbeatData;
serializeJson(doc, heartbeatData);
ApiClient.setInsecure(); //skip verification of SSL cert
Serial.println("Sending Heartbeat");
ApiHttpClient.begin(ApiClient, DIGITAL_HQ_HEARTBEAT_ENDPOINT);
ApiHttpClient.addHeader("Content-Type", "application/json");
ApiHttpClient.setUserAgent(DIGITAL_HQ_USER_AGENT);
int responseCode = ApiHttpClient.POST(heartbeatData); // just post, Don't care about the response.
if (responseCode != 200) {
failedApiCalls ++;
}
Serial.print("ResponseCode from heartbeat: ");
Serial.println(responseCode);
// Free resources
ApiHttpClient.end();
this code runs on core 0, via the following function;
xTaskCreatePinnedToCore(sendHeartBeat, "Send Heartbeat", 20000, NULL, 25, &heartBeatTask, 0);
I do call the heartbeat once in the main core, then it works, but then on the second core, it sometimes does, but other times, it doesnt.
There is nothing too fancy about this, I think and I really can't seem to figure this one out...
Side notes:
There is an MQTT connection running to the AWS IoT hub, on core 1, where I don't have any issues with.
I currently run into same troubles after updating the libraries, old code for esp32 http clients stopped to work with the same symptoms.
I could solve this by switching to simply use HTTPClient only, without WiFiClientSecure. And it works with https.
#include <HTTPClient.h>
#include <Arduino_JSON.h>
void getPricesFromKraken(){
String url = "https://api.kraken.com/0/public/Ticker?pair=DOGEUSD,XBTUSD";
HTTPClient http;
JSONVar data;
http.begin(url.c_str());
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
String payload = http.getString();
data = JSON.parse(payload);
Serial.println(data);
}
else {
Serial.printf("http response code: %d\n", httpResponseCode);
}
http.end();
}

Node js server and c++ client socket io connection , not able to emit or read the data

I cannot get this simple test work. I wrote to the client in C++ and the server in NodeJS, both running on my computer. When I execute the client application, the console outputs this text...but the event 'key' is never fired on the server!
Client console output:
Error: No active session
[2019-11-21 17:30:11] [connect] Successful connection
[2019-11-21 17:30:11] [connect] WebSocket Connection 127.0.0.1:8081 v-2 "WebSocket++/0.8.1" /socket.io/?EIO=4&transport=websocket&t=1574353811 101
C++ client
#include "pch.h"
#include <iostream>
#include <sio_client.h>
using namespace sio;
using namespace std;
int main()
{
sio::client io;
io.connect("http://127.0.0.1:8081");
string command = "w";
io.socket()->emit("key", command );
}
NodeJS server
'use strict';
const express = require('express');
const app = express();
const serverHttp = require('http').Server(app);
const io = require('socket.io')(serverHttp);
const port = 8081;
io.on('connection', function (socket) {
// Never fired :(
socket.on('key', function (data) {
console.log("key received!!!");
});
});
serverHttp.listen(port, function() {
console.log("init!!!");
});
could you please fix this, I saw someone asking the same question in the GitHub issues section for socket io c++ client, no one has answered yet. please help out
From a brief look through the code it seems that io.connect starts a separate thread to do the networking. When it returns the socket is very likely still in a connecting state.
The code for .emit ends up here, which pushes a packet onto the queue and simply returns if the socket is not connected yet.
So I think the root cause of your problem is that the application exits before the network thread has had a chance to finish connecting.
The stupidest way to fix this is to simply add a sleep statement at the end of your main function, to give the network thread a chance to connect and get its message through. A slightly better way is to use socket.set_open_listener to get notified when the connection has been opened, and then send the message, because that should go through immediately:
sio::client io;
io.set_open_listener([&]() {
io.socket()->emit("key", command);
});
io.connect("http://127.0.0.1:8081");
This constructs and passes a lambda to set_open_listener, where it is stored as a std::function<void(void)> internally.

detect client connection closed in the grpc server

In the unary RPC example provided in the grpc Github (client) and (server), is there any way to detect client's closed connection?
For example, in server.cc file:
std::string prefix("Hello ");
reply_.set_message(prefix + request_.name());
// And we are done! Let the gRPC runtime know we've finished, using the
// memory address of this instance as the uniquely identifying tag for
// the event.
status_ = FINISH;
int p = 0,i=0;
while(i++ < 1000000000) { // some dummy work
p = p + 10;
}
responder_.Finish(reply_, Status::OK, this);
With this dummy task before sending the response back to the client, server will take a few seconds. If we close the client (for example say with Ctrl+C), the server does not throw any error. It simply calls Finish and then deallocates the object as if the Finish is successful.
Is there any async feature (handler function) on the server-side to get us notified that the client has closed the connection or client is terminated?
Thank You!
Unfortunately, no.
But now guys from gRPC team works hard to implement callback mechanism into C++ implementation. As I understand it will work the same way as on Java implementation( https://youtu.be/5tmPvSe7xXQ?t=1843 ).
You can see how to work with future API with next examples: client_callback.cc and server_callback.cc
And the point of your interest there is ServerBidiReactor class from ::grpc::experimental namespace for server side. It have OnDone and OnCancel notification methods that maybe can help you.
Another interesting point there is that you can store a pointers to connection object and send notifications to client at any time.
But it still have many issue and I don't recommend to use this API in production code.
Current progress of C++ callbacks implementation you can see there: https://github.com/grpc/grpc/projects/12#card-12554506

How to properly use QWebSocket::sendBinaryMessage() method from a C++ client?

There are C++ Qt client & server. Following code works fine and the connection happens between the client and the server:
QWebSocket webSocket; // defined somewhere
...
QUrl url;
url.setScheme("ws"); // SSL encryption disabled
url.setHost(serverName); // "127.0.0.1" (can be "www.abc.com" too)
url.setPort(portNumber); // 2000
webSocket.open(url); // connects with the server properly
PRINT(url.toString()); // output: "ws://127.0.0.1:2000"
While sending the binary data, the function returns 0 instead of the number of bytes:
// though the message.size() is 80 bytes; the method returns 0
webSocket.sendBinaryMessage(QByteArray(message.data(), message.size()));
Note that, the QWebSocketServer works as expected.
We also have a Javascript client. That connects & sends the binary message properly. The only addition in that client is below:
webSocketJS.binaryType = "arraybuffer"; // <--- Javascript code
But such provision is not found in QWebSocket or I may have missed it.
Question: How to correctly send the binary data over the web connection?
For those interested, the server [pseudo] code is like below:
auto pWebSocket = WebServer.nextPendingConnection();
QObject::connect(pWebSocket, &QWebSocket::binaryMessageReceived,
[&] (const QByteArray& message) { DataRead(message, rManager); }); // This slot is not called as of now
It seems that there is no mention of how the QWebSocket::connected() signal is treated.
Due to internet delay and initial handshakes, the WebSocketServer may take some time to establish a connection. Ideally the binary/text message should be sent only after the connected() is received.
Before making a connection using webSocket.open(url), you should be handling this signal:
... // same code
QObject::connect(&webSocket, &QWebSocket::connected,
[&] ()
{
webSocket.sendBinaryMessage(QByteArray(message.data(), message.size()));
// ... set some internal state suggesting the established connection
}
webSocket.open(url);
Above is just a pseudo code to show that the first sendBinaryMessage() should be sent after the connect() signal. Ideally in real world code, you may want to set some state, which informs the client that the connection is established.
Similarly as mentioned in the comments, we should be checking for errors and disconnections as well.