-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem trying when trying to comunicate with Typescript websocket #76
Comments
Okay... I'll send you the code with I'm very happy; you made the code very easy to understand. You did a great job! However, you missed some details about Byter. |
Oh right... i forgot about byter... D + (bytes length of ProtocolKey) + ProtocolKey + D + (bytes length of Event_Name) + Event_Name + "Prefix of data " + (bytes length of data if need, like for bytes or string) + the data bytes Pretty much i forgot to include the overhead right? that make sense.... |
I can send event now, I'm impl. about receiving events to.
|
Give 30min more, I'm on final. |
Oh, thank you so much! But I didn't mean to rush you, I was just asking to understand if that was the issue :) |
Nan... I always had on mind to create bind to TypeScript and Python, because i know people frequetly should use those language as client or server. (-_-.. |
Netly with Javascript / TypescriptThis project includes EventManager for TypeScript (and JavaScript). .NET sidepublic class Logger
{
public static Logger Instance { get; set; } = new Logger();
public Action<string> Error { get; set; } = Console.WriteLine;
public Action<string> Information { get; set; } = Console.WriteLine;
} public class Program
{
public static void Main(string[] args)
{
var network = new NetworkManager("127.0.0.1", 8080);
network.Connect().GetAwaiter().GetResult();
Thread.Sleep(TimeSpan.FromDays(1));
Logger.Instance.Information("Exit: 0");
}
} using Byter;
using Netly;
public class NetworkManager : IDisposable
{
private readonly string _ip;
private readonly int _port;
private readonly HTTP.Server _server = new();
public NetworkManager(string ip, int port)
{
_ip = ip;
_port = port;
_server.On.Open(() => Logger.Instance.Information($"Websocket server started on '{_ip}:{_port}'"));
_server.On.Close(() => Logger.Instance.Information("Websocket server stopped"));
_server.On.Error(error => Logger.Instance.Error($"Websocket error: {error}"));
_server.Map.WebSocket("/API", (_, ws) =>
{
ws.On.Event((name, bytes, type) => Logger.Instance.Information($"Received event {name} - {bytes} *{type}"));
ws.On.Open(() => Logger.Instance.Information("Client Connected."));
ws.On.Close(() => Logger.Instance.Information("Client Disconnected."));
ws.On.Error(error => Logger.Instance.Error($"Websocket error: {error.Message}"));
ws.On.Data((data, type) =>
{
_server.To.WebsocketDataBroadcast("Sample.Data.Ping", HTTP.Binary);
Logger.Instance.Information($"Websocket server data: {data.GetString()} - *{type}");
});
ws.On.Event((name, data, type) =>
{
_server.To.WebsocketEventBroadcast("Event.Name", "Sample.Event.Ping", HTTP.Binary);
Logger.Instance.Information($"Websocket server event ({name}): {data.GetString()} *{type}");
});
});
}
public void Dispose()
{
Close();
GC.SuppressFinalize(this);
}
public Task Connect() => _server.To.Open(new Uri($"https://{_ip}:{_port}"));
private void Close() => _server.To.Close().GetAwaiter().GetResult();
} Node.js side (TypeScript)"index.ts";
import WebSocketClient from "./WebsocketClient";
console.log("Initializing websocket client...");
let client: WebSocketClient = WebSocketClient.GetSingletonInstance(); "WebsocketClient.ts";
import {Buffer} from "buffer";
import EventManager from "./EventManager";
export default class WebSocketClient {
private static instance: WebSocketClient;
private socket: WebSocket;
private isConnected: boolean
private isConnecting: boolean
private readonly ip: string
private readonly port: number
constructor(ip: string, port: number) {
this.isConnected = false;
this.isConnecting = false;
this.ip = ip;
this.port = port;
this.socket = new WebSocket(`ws://${this.ip}:${this.port}/API`);
this.socket.binaryType = "arraybuffer";
this.socket.onopen = () => {
console.log("Websocket client connected");
// send welcome...
this.SendData("hello server, from data.");
this.SendEvent("Welcome", "Hello server, from event.");
};
this.socket.onerror = (error) => {
console.error("Websocket client error:", error);
};
this.socket.onclose = () => {
console.log("Websocket client disconnected");
};
this.socket.onmessage = (event) => {
let eventMessage = EventManager.Verify(event.data);
if (eventMessage) {
console.log(`Websocket received event (${eventMessage.name}): ${this.GetString(eventMessage.data)}`);
} else {
console.log(`Websocket data received: ${this.GetString(event.data)}`);
}
};
}
public static GetSingletonInstance(): WebSocketClient {
if (!WebSocketClient.instance) {
WebSocketClient.instance = new WebSocketClient("127.0.0.1", 8080);
}
return WebSocketClient.instance;
}
private IsConnected(): boolean {
return this.socket.readyState === WebSocket.OPEN;
}
public SendData(buffer: ArrayBuffer | string): void {
if (!this.IsConnected() || !buffer) return;
this.socket.send(buffer)
}
public SendEvent(name: string, buffer: ArrayBuffer | string): void {
if (!buffer || !name || name.length <= 0) return;
let eventBuffer: ArrayBuffer = (typeof buffer === "string") ? Buffer.from(buffer) : buffer;
if (eventBuffer.byteLength <= 0) return;
this.SendData(EventManager.Create(name, eventBuffer));
}
public GetString(buffer: ArrayBuffer): string {
const decoder = new TextDecoder("utf-8");
return decoder.decode(buffer);
}
} import {Buffer} from "buffer";
"EventManager.ts"
export default class EventManager {
static ProtocolKey: string = "Ny://";
static protocolBuffer = this.Write(this.ProtocolKey, "ascii");
public static Create(name: string, buffer: ArrayBuffer): ArrayBuffer {
const nameBuffer = this.Write(name, "utf8")
const dataBuffer = this.Write(buffer, "ascii");
return this.ConcatBuffers(this.protocolBuffer, nameBuffer, dataBuffer);
}
public static Verify(buffer: ArrayBuffer): { name: string, data: ArrayBuffer } | null {
/*
* p = Prefix (2 bytes)
* s = Size/Length (4) bytes
* b = Buffer (1+) bytes
p. s. b. p. s. b+ p. s. b+ */
if (buffer.byteLength < this.protocolBuffer.byteLength) return null;
try {
let offset: number = 0;
const protocol: ArrayBuffer = buffer.slice(offset, this.protocolBuffer.byteLength + offset);
// compare protocol buffer
{
if (!this.CompareBuffer(protocol, this.protocolBuffer)) return null;
offset += protocol.byteLength;
}
const prefix = new ArrayBuffer(2);
const view = new DataView(prefix);
view.setUint8(0, 76);
view.setUint8(1, 0);
const receivedNamePrefix: ArrayBuffer = buffer.slice(offset, 2 + offset);
if (!this.CompareBuffer(prefix, receivedNamePrefix)) return null;
offset += 2;
const nameSizeBuffer: ArrayBuffer = buffer.slice(offset, 4 + offset);
const nameSizeValue: number = this.NumberFromLittleEndianBytes(nameSizeBuffer);
offset += 4;
if (nameSizeValue <= 0 || nameSizeValue > buffer.byteLength - offset) return null;
const name: string = this.BufferToString(buffer.slice(offset, nameSizeValue + offset));
offset += nameSizeValue;
view.setUint8(0, 66);
view.setUint8(1, 0);
const receivedDataPrefix = buffer.slice(offset, 2 + offset);
if (!this.CompareBuffer(prefix, receivedDataPrefix)) return null;
offset += prefix.byteLength;
const bufferSizeBuffer: ArrayBuffer = buffer.slice(offset, 4 + offset);
const bufferSizeValue: number = this.NumberFromLittleEndianBytes(bufferSizeBuffer);
offset += bufferSizeBuffer.byteLength;
if (bufferSizeValue <= 0 || bufferSizeValue > buffer.byteLength - offset) return null;
const data: ArrayBuffer = buffer.slice(offset, bufferSizeValue + offset);
return {name: name, data: data}
} catch (e) {
return null;
}
}
public static Write(value: string | ArrayBuffer, encoding: "utf8" | "ascii"): ArrayBuffer {
const isBinary = (typeof value != "string");
const buffer: ArrayBuffer = isBinary ? value : Buffer.from(value, encoding);
const size: ArrayBuffer = this.NumberToLittleEndianBytes(buffer.byteLength);
const prefix: ArrayBuffer = new ArrayBuffer(2);
{
const view = new DataView(prefix);
if (isBinary) {
// write 'B' char in bytes (string prefix) [66,00]
view.setUint8(0, 66);
view.setUint8(1, 0);
} else {
// write 'L' char in bytes (string prefix) [76,00]
view.setUint8(0, 76);
view.setUint8(1, 0);
}
}
return this.ConcatBuffers(prefix, size, buffer);
}
public static NumberToLittleEndianBytes(value: number): ArrayBuffer {
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint32(0, value, true);
return new Uint8Array(buffer).buffer;
}
public static NumberFromLittleEndianBytes(value: ArrayBuffer): number {
const view = new DataView(value);
return view.getUint32(0, true);
}
public static ConcatBuffers(...buffers: ArrayBuffer[]): ArrayBuffer {
const size = buffers.reduce((x, buffer) => x + buffer.byteLength, 0);
let offset = 0;
const result = new Uint8Array(size);
buffers.forEach(buffer => {
const bytes = new Uint8Array(buffer);
result.set(bytes, offset);
offset += bytes.byteLength;
});
return result.buffer;
}
public static CompareBuffer(a: ArrayBuffer, b: ArrayBuffer): boolean {
if (a === b) return true;
if (a.byteLength !== b.byteLength) {
return false;
}
const viewA = new Uint8Array(a);
const viewB = new Uint8Array(b);
for (let i = 0; i < viewA.length; i++) {
if (viewA[i] !== viewB[i]) {
throw new Error(`Invalid data: [${i}] ${viewA[i]} ${viewB[i]}`);
}
}
return true;
}
public static BufferToString(buffer: ArrayBuffer): string {
const decoder = new TextDecoder("utf-8");
return decoder.decode(buffer);
}
} I tested it and it's working perfectly. I hope this implementation helps you! <3. Ooh My God!!! |
Nice! it work very well! thank you man! |
Ooh!!! Enjoy... I never had working with bytes before on js/ts <3. Hope success on your project/s |
Any question: you are welcome! (ˆ _**.. |
So i'm trying to comunicate with a react app, sending data seems to work really good but i got troubles sending events.
I'm using the library Buffer to replicate the EventManager but without success.
Pretty sure is something wrong that i'm doing but can't figure it out.
Any help would be much appreciated!
Here some screenshots / the code i'm using
Sent Event:
Received Event:
Received Data:
The text was updated successfully, but these errors were encountered: