So I am trying to setup a client websocket in a Javascript file talking to a server written in C#.
Client:
var socket = new WebSocket("ws://localhost:11000");
function barf() {
socket.send('asdf');
}
socket.onmessage = function(e){
console.log(e.data);
};
Server:
IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
IPAddress ipAddress = ipHostInfo.AddressList[1];
TcpListener listener = new TcpListener(ipAddress, 11000);
try
{
listener.Start();
TcpClient client = listener.AcceptTcpClient();
message = client.GetStream();
int i = message.Read(bytes);
string data = Encoding.ASCII.GetString(bytes, 0, i);
string key = new System.Text.RegularExpressions.Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim();
Byte[] response = GetHandshakeResponse(key);
message.Write(response, 0, response.Length);
bytes = new Byte[1024];
i = message.Read(bytes);
Console.WriteLine(Encoding.ASCII.GetString(bytes));
}
The issue is that when I call the function 'barf' in my Javascript file, the server spits out a different message each time as if it were being encrypted. I have tried using different encodings and I can't seem to end up with exactly 'asdf' on the server. Does anyone have any insight? Thanks!
If you want to encrypt communication over web sockets, use the wss protocol instead of ws.
Also, I don't think your test is meaningful, because you haven't run it with a server socket server on the back end.
Creating a "Hello World" WebSocket example
Related
I'm definitely a newbie with JS and node. I have telescope management software called SkyX Pro, and it has the ability to run a TCP Server on port 3040. I can connect to it using Netcat and hand it a Javascript starting with //* Javascript *// this works and allows me to startup cameras and other equipment and send commands for taking pictures etc. The issue is it needs to be run from a batch file which makes getting any information back to an HTML page tough (Like Camera, focuser and filter wheel status and temperatures).
The NC call looks like "NC localhost 3040 < Javascript-file.js
To get around the browser to local machine security issues I want to run this from node.js with maybe socket.io-client if possible, but I don't know the proper syntax for it.
I have seen plenty of client syntax sending hello's etc. but nothing send javascript and allowing for two-way connectivity that I can understand.
I have tried using:
var socket = io.connect('http://localhost');`enter code here`
socket.on('httpServer', function (data) {
console.log(data);
document.write(data + "\r\n");
socket.emit('tcp', "For TCP");
});
const net = require('net');
const client = new net.Socket();
client.connect({ port: 3040, host: process.argv[2] });
client.on('data', (data) => {
console.log(data.toString('utf-8'));
But I do not understand it well enough to troubleshoot why it's not working.
Any help would be wonderful, and please treat me like a baby that needs its step by step.
Cheer
Peter
Reading [1], We can assume socket-io isn't the perfect fit for you, because that Server you have sound like a typical tcp-socket server, not a socket.io server ( which requires special headers ) or a web-socket server.
So you only needs "net" library to do the job.
const net = require('net');
// module to send a message to TCP-socket server and wait for the response from socket-server
const sendAndReceive = async (client, message) => {
client.write(message);
let response = null
await ( new Promise( (resolve, reject) => {
client.on('data', function(data) {
response = data;
resolve()
});
}))
return response;
}
// send a single message to the socket-server and print the response
const sendJSCode = (message) => {
// create socket-client
const client = new net.Socket();
client.connect(3040, 'localhost', async function() {
console.log('Connected');
// send message and receive response
const response = await sendAndReceive(client, message)
// parse and print repsonse string
const stringifiedResponse = Buffer.from(response).toString()
console.log('from server: ', stringifiedResponse)
// clean up connection
client.destroy()
});
}
sendJSCode('var Out; \n Out="TheSky Build=" + Application.build \n\r')
This script will:
Initiate a socket client
on connection successfully, client sends a message
client receives back response from that message
client prints response to terminal
Note that TheSkyX has a limitation of 4096 bytes for each message[2], any more than that and we will need to chunk the message. So you may want to keep the js-code short and precise.
that snippet I gave is minimal, it doesn't handle errors from server. If you want, you can add client.on("error", .. ) to handle it.
Your point of connecting to the socket server directly from browser is very intriguing, unfortunately it is not allowed by modern browsers natively due to security concerns 3
[1] https://socket.io/docs/#What-Socket-IO-is-not:~:text=That%20is%20why%20a%20WebSocket%20client,to%20a%20plain%20WebSocket%20server%20either.
[2] https://www.bisque.com/wp-content/scripttheskyx/scriptOverSocket.html#MSearchField:~:text=set%20to%204096%20bytes
I'm trying to connect java Server and Javascript client with socket.io. When i see the debugger at browser, it looks like the data is being received, but i'm getting this error: "Reason: CORS header 'Access-Control-Allow-Origin' missing" and i am not being able to print data at client-side.
import...
public class MeuServerSocket {
//initialize socket and input stream
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream in = null;
public MeuServerSocket(int port) {
// starts server and waits for a connection
try {
while(true){
server = new ServerSocket(port);
System.out.println("Server started");
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted");
ObjectOutputStream saida = new ObjectOutputStream(socket.getOutputStream());
saida.flush();
// send available data from server to client
saida.writeObject("Texto enviado 123...");
// takes input from the client socket
in = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
String line = "";
// reads message from client until "Over" is sent
boolean fim = false;
while (!line.equals("Over") && !fim)
{
try
{
line = in.readUTF();
System.out.println(line);
}
catch(IOException i)
{
fim = true;
System.out.println(i.toString());
}
}
System.out.println("Closing connection");
// close connection
socket.close();
saida.close();
in.close();
}
} catch (IOException i) {
System.out.println(i);
}catch(Exception e){
System.out.println(e.toString());
}
}
public static void main(String[] args) {
MeuServerSocket server = new MeuServerSocket(5000);
}
}
var socket = io('http://localhost:5000');
socket.on('connect', function () {
socket.send('hi \nOver');
socket.on('get', function (msg) {
// my msg
console.log('msg: '+msg)
})
socket.on('disconnect',()=>{
console.log('disconnected')
})
})
When i look at Firefox network, i see that the data was sent inside one of the packages...
https://imgur.com/vDAS00B
The biggest issue I'm seeing here is a misunderstanding of socket.io. Socket.io for javascript is not compatible with the Socket library in java. The naming conventions can be confusing for sure.
socket.io is a library that is related to web sockets (ws://). It implements all the basic websocket features plus some bonuses.
What you have for your java code is a TCP socket server. While websockets and socket.io are built on TCP socket, you can not connect a socket.io client to a "naked" socket server.
SOLUTION:
If your javascript is running from nodejs, you can use their net library found here. If you are running javascript from a webbrowser, than you are limited to websockets, which means you're going to change your java code to a websocket server. You can find a library for that somewhere online.
TLDR: Use ws://... instead of http://....
Details:
https is used for HTTP protocol. In such case it is correct that browser first asks your server if CORS is allowed. You have not enabled CORS. That's why it is normal that browser refuses to send CORS request.
But you say you want to use Web Sockets. Then you should use ws://, not http://. For Web Sockets there is no CORS policy and browser will send your request without CORS restrictions.
My problem is that the current solution I have for sending a specific socket using the library "ws" with node.js is not good enough.
The reason is because if I connect with multiple tabs to the websocket server with the same userid which is defined on the client-side, it will only refer to the latest connection with the userid specified.
This is my code:
// Server libraries and configuration
var server = require("ws").Server;
var s = new server({ port: 5001});
// An array which I keep all websockets clients
var search = {};
s.on("connection", function(ws, req) {
ws.on("message", function(message){
// Here the server process the user information given from the client
message = JSON.parse(message);
if(message.type == "userinfo"){
ws.personName = message.data;
ws.id = message.id;
// Defining variable pointing to the unique socket
search[ws.id] = ws;
return;
}
})
})
As you can see, each time a socket with same id connects, it will refer to the latest one.
Example If you did not understand:
Client connect to server with ID: 1337
search[1337] defined as --> websocket 1
A new connection with same ID: 1337
search[1337] becomes instead a variable refering to websocket 2 instead
Websockets provide a means to create a low-latency network "socket" between a browser and a server.
Note that the client here is the browser, not a tab on a browser.
If you need to manage multiple user sessions between the browser and server, you'll need to write code to do it yourself.
I would like to send JSON data from a Java Application to a JavaScript. The JSON is log/statistical data which I would like to format with JavaScript and view in the browser in realtime.
I tried it through a Socket but JavaScript's WebSocket does not really accept the Socket from Java. Firefox tells me that it can't establish an connection to ws://localhost:8000.
Java Socket
ServerSocket serverSocket = new ServerSocket(8000);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out.println("Message");
JavaScript WebSocket
var exampleSocket = new WebSocket("ws://localhost:8000");
exampleSocket.onmessage = function (event) {
console.log(event.data);
};
If this is not possible because of incompatability. What would be the simplest way to send JSON to JavaScript?
There actually is a WebSocket implementation for Java:
http://www.html5rocks.com/en/tutorials/websockets/basics/
Then under Server Side Implementations > Java > Jetty
http://www.eclipse.org/jetty/
After toying around with this for hours, I simply cannot find a solution. I'm working on a WebSocket server using "node.js" for a canvas based online game I'm developing. My game can connect to the server just fine, it accepts the handshake and can even send messages to the server. However, when the server responds to the client, the client doesn't get the message. No errors, nothing, it just sits there peacefully. I've ripped apart my code, trying everything I could think of to fix this, but alas, nothing.
Here's a stripped copy of my server code. As I said before, the handshake works fine, the server receives data fine, but sending data back to the client does not.
var sys = require('sys'),
net = require('net');
var server = net.createServer(function (stream) {
stream.setEncoding('utf8');
var shaken = 0;
stream.addListener('connect', function () {
sys.puts("New connection from: "+stream.remoteAddress);
});
stream.addListener('data', function (data) {
if (!shaken) {
sys.puts("Handshaking...");
//Send handshake:
stream.write(
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n"+
"Upgrade: WebSocket\r\n"+
"Connection: Upgrade\r\n"+
"WebSocket-Origin: http://192.168.1.113\r\n"+
"WebSocket-Location: ws://192.168.1.71:7070/\r\n\r\n");
shaken=1;
sys.puts("Handshaking complete.");
}
else {
//Message received, respond with 'testMessage'
var d = "testMessage";
var m = '\u0000' + d + '\uffff';
sys.puts("Sending '"+m+"' to client");
var result = stream.write(m, "utf8");
/*
Result is equal to true, meaning that it pushed the data out.
Why isn't the client seeing it?!?
*/
}
});
stream.addListener('end', function () {
sys.puts("Connection closed!");
stream.end();
});
});
server.listen(7070);
sys.puts("Server Started!");
Here's my client side code. It uses Chrome native WebSockets.
socket = new WebSocket("ws://192.168.1.71:7070");
socket.onopen = function(evt) {
socket.send("blah");
alert("Connected!");
};
socket.onmessage = function(evt) {
alert(evt.data);
};
var m = '\u0000' + d + '\uffff';
var result = stream.write(m, "utf8");
Ah, that seems not quite right. It should be a zero byte, followed by a UTF-8 encoded string, followed by a 0xFF byte.
\uFFFF does not encode in UTF-8 to a 0xFF byte: you get 0xC3 0xBF. In fact no character will ever produce an 0xFF in UTF-8 encoding: that's why it was picked as a terminator in WebSocket.
I'm not familiar with node.js, but I would guess you'd need to say something like:
stream.write('\u0000'+d, 'utf-8');
stream.write('\xFF', 'binary');
Or manually UTF-8 encode and send as binary.
The handshaking is also questionable, though I guess it's a simple-as-possible first draft that's probably working for you at the moment. You're relying on the first packet being the whole handshake header and nothing else, then the second packet being the payload data. This isn't at all guaranteed. You'll probably want to collect data in a buffer until you see the 0x0D 0x0A 0x0D 0x0A marker for the end of the headers, then check the header content and possibly return the 101, then continue from data after that marker.