Why is the c# websocket client not receiving data? - javascript

There is a very good utility called ttyd, which allows you to run a console application on your computer and display this console in the browser.
After startup, the utility starts an http web server on the specified port and when accessing localhost, a website with a web application that connects using web sockets to localhost:<port>/ws, and already with the help of them there is communication between the web application and the ttyd agent running on the computer.
I want to implement a client for ttyd in c#. I studied with the help of chrome tools what data the web application sends before receiving the data output to the console. This is just a string: {"authToken":"","columns":211,"rows":46} and tried to repeat the same actions in the c# client. But for some reason, no data from ttyd is returned to me.
Comparing the data output by ttyd to its console in the OS itself, it can be seen that it does not even create a process when accessing from my client.
Here is the code I use with the Websocket.Client package
var exitEvent = new ManualResetEvent(false);
var url = new Uri("ws://localhost:7681/ws");
using (var client = new WebsocketClient(url))
{
client.ReconnectTimeout = TimeSpan.FromSeconds(30);
client.ReconnectionHappened.Subscribe(info =>
Console.WriteLine($"Reconnection happened, type: {info.Type}"));
client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message received: {msg}"));
client.Start();
Task.Run(() => client.Send("{\"AuthToken\":\"\",\"columns\":211,\"rows\":46}"));
exitEvent.WaitOne();
}
I have absolutely no idea how to get ttyd to send data to my client. Do you have any idea what action the browser is doing I'm missing in my c# client?
I tried different libraries for web sockets in c#, and also used postman with copying all the headers that the original web application sends to the ttyd agent, but this does not change anything. That is, ttyd, something is fundamentally interfering, as if my web client is not doing something that the browser is doing.

Related

Browser Notification Push Service: How to specify push server?

I'm trying to set up push notifications for a browser web app.
I found the following code can be used to subscribe to a push server. Running a simple push server locally seems to work fine, but
Q: I was wondering how I would specify the push server if it wasn't local?
I mean, how would the browser know where to subscribe to just by looking at the public key of the server?
function createNotificationSubscription(pushServerPublicKey) {
return navigator.serviceWorker.ready.then(
(serviceWorker) => {
return serviceWorker.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey: pushServerPublicKey
})
.then((subscription) => {
console.log("✅ User is subscribed.", subscription);
return subscription;
});
}
);
}
References:
https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe
how do I specify the push server [...]?
You don't.
if it wasn't local?
There is a misunderstanding.
The push server will always be a fixed server given by the browser vendor.
It basically works like this:
You subscribe()
This request goes to the notification server of the browser vendor (mozilla, google, ...).
That server will create a so called push endpoint - just a fancy word for URL. This URL serves as a mailbox: If someone sends a message to it, the push server (still being the server of the browser vendor) will forward it to the browser (client).
The server will return the push endpoint and some other information as a result of your initial subscribe().
Currently only the push server and your web app know about the push endpoint....
So your web app needs to the whole result of subscribe to the application server (which is your server).
Now your server is able to use that information to send messages to the push server. The push server will then forward the message to the client.
Here's also a flow chart depicting the flow with a little more detail in regard of the different players:
Push service: Service running on the browser vendor's server
Subscription information: URL of the push endpoint along with some keys.

How to communicate between Python3 and JavaScript via sockets

I just set up a small TCP-socket server in python3, which waits for a connection, sends a small encoded text and waits for data from the client.
Python-Code:
import socket
sock = socket.socket()
sock.bind(("0.0.0.0", 20000))
sock.listen(5)
while True:
Client, address = sock.accept()
Client.send("ping".encode())
print(Client.recv(1024).decode()) # Here I want to receive data from the client
Client.close()
At the end, there should be a browser interface which can communicate with the python backend with JQuery or just something that receive and send (With data!) sockets.
Thank you :D
EDIT:
Forgot to say that I can receive the text in a browser, I just need to know how to send data back.
if you need to connect to a NodeJS javascript environment then you should take a look at this native package
https://nodejs.org/api/net.html#class-netsocket
if you need to connect to a browser javascript environment then you should take a look at WebSockets
Python: https://websockets.readthedocs.io/en/stable/#:~:text=websockets%20is%20a%20library%20for,an%20elegant%20coroutine%2Dbased%20API.
Javascript https://developer.mozilla.org/es/docs/Web/API/WebSockets_API

No notifications from characteristicvaluechanged in web bluetooth

I have a LM068 BLE serial adapter which I'm trying to communicate with from a web app. I have tested it from the nRF Connect app on Android, where the communication works fine.
The characteristic has the properties "notify" and "writeWithoutResponse".
When calling characteristic.startNotifications() I get an error "GATT Error: invalid attribute length.".
Calling characteristic.writeValue() successfully sends the data, and I can see the incoming data in my serial monitor. When sending data from the serial terminal, the characteristicvaluechanged event never fires. Notifications works from the nRF Connect app.
This is part of my current code:
const characteristic = await service.getCharacteristic(characteristicName)
try {
await characteristic.startNotifications()
} catch (e) {
console.log(e.message)
// GATT Error: invalid attribute length.
}
const encoder = new TextEncoder('utf-8')
characteristic.writeValue(encoder.encode('test')) // Works
characteristic.addEventListener('characteristicvaluechanged', handleValueChanged) // Never gets called
So it turns out that the way I was testing the web app was the issue. I didn't have a BLE dongle for my workstation, so I was using my phone to access my development server. Of course web bluetooth needs to be either run on localhost or from https, so I simply ran the development server on https and accessed it on the network from my phone (like https://192.168.0.x). I proceeded even though chrome deemed it unsafe, but apparently only part of web bluetooth works this way.
Pairing and writeWithoutResponse works with an unsigned certificate. Notifications does not.
I'm leaving this here in case anyone else makes the same mistake.

Display Kafka messages on web page

I have a Java Spring Application with a Tomcat server that listen on kafka topic. I want to display all messages in a real-time mode on the web page. Therefore, when a kafka messages is arrived in the backend I want to see it on my web page. I don't know a good approach to push kafka message directly to the front-end and display it on web page. Is someone could help my with a solution and some examples that could help? Thanks!
I have implemented a system like this in Java for my last employer, albeit not with Spring/Tomcat. It was consuming messages from Kafka and serving them on a web socket to be displayed in the browser. The approach I followed was to use akka-stream-kafka and akka-http for web-socket support. The benefit of that is both are based on akka-streams which makes it an easy fit for streaming data.
While you can embed akka-http in your spring app running inside tomcat, it may not feel the most natural choice any more as spring framework already has its own support for both kafka and websockets. However, if you're not familiar with either, then jumping on the akka approach may be easiest and the core logic goes along these lines (I can't share the code from work so have just put this together from the examples in the docs, not tested):
public Route createRoute(ActorSystem system) {
return path("ws", () -> {
ConsumerSettings<byte[], String> consumerSettings = ConsumerSettings.create(system, new ByteArrayDeserializer(), new StringDeserializer())
.withBootstrapServers("localhost:9092")
.withGroupId(UUID.randomUUID().toString()) //this is so that each client gets all messages. To be able to resume from where a client left off in case of disconnects, you can generate in on the client side and pass in the request
.withProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest")
return handleWebSocketMessages(
Flow.fromSinkAndSourceCoupled(
Sink.ignore(),
Consumer.committableSource(consumerSettings, Subscriptions.topics("topic1"))
.map(msg -> TextMessage.create(msg.record().value()))
)
);
}
}
To expose this route you can follow the minimalistic example, the only difference being the route you define needs the ActorSystem:
final Http http = Http.get(system);
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Flow<HttpRequest, HttpResponse, NotUsed> routeFlow = createRoute(system).flow(system, materializer);
final CompletionStage<ServerBinding> binding = http.bindAndHandle(routeFlow,
ConnectHttp.toHost("localhost", 8080), materializer);
Once you have your messages published to the websocket, the front end will code will of course depend on your UI framework of choice, the simplest code to consume ws messages from javascript is:
this.connection = new WebSocket('ws://url-to-your-ws-endpoint');
this.connection.onmessage = evt => {
// display the message
To easily display the message in the UI, you want the format to be something convenient, like JSON. If your Kafka messages are not JSON already, that's where the Deserializers in the first snippet come in, you can convert it to a convenient JSON string in the Deserializer or do it later on in the .map() called on the Source object.
Alternatively, if polling is an option you can also consider using the off-the-shelf Kafka Rest Proxy, then you only need to build the front-end.

When using SignalR how does my Web Server know where localhost is?

I am using SignalR in a web application that is hosted on a separate server that has nothing to do with the client.
In the code, I have a function that connects to a SignalR Self-Hosted Service (C#) that is running on the client's computer who is clicking / doing things on the web application (it has been installed by the client). If the client clicks a certain button on my web application, then my service will get data sent to it from the JavaScript code since my server is running on http://*:8080.
Everything appears to be working fine. My question is, how?
My web application is setting the connection in the Server Side JS Code to say this
MyWebApp.cshtml
//Set the hubs URL for the connection
$.connection.hub.url = "http://localhost:8080/signalr";
My C# Service running on the client's computer in the background (that has been installed) is saying this:
MyService.cs
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("Service started");
//string url = "http://localhost:8080";
string url = "http://*:8080";
SignalR = WebApp.Start(url);
eventLog1.WriteEntry("Server running on " + url);
}
How is it possible that they are even communicating when the server side code is saying "Hey look for localhost on 8080!"
And the service says "Hey start on *:8080!" ( I don't even understand what * means)
Last but not least, if I uncomment the line in my service that is currently commented out and use that to start the service it will not work! Why will my service start up on http//*:8080 but not on http://localhost:8080 ?
This code:
WebApp.Start("http://*:8080")
Says "listen for connections on port 8080 on any IP address available". So it will bind to localhost (127.0.0.1) and any other assigned IP addresses the machine has. It is basically a wildcard binding.
This code:
$.connection.hub.url = "http://localhost:8080/signalr";
Says the server is on localhost which resolves to 127.0.0.1.
For your last point as to why it doesn't work if the server started on http://localhost:8080, I assume this is because SignalR is having trouble mapping to the correct IP address. Try using http://127.0.0.1:8080 instead.

Categories