I'm just trying to get a very basic websocket connection over internet. The code seems fine - because it works when connecting to localhost - but for some reason fails when I try to use it over the internet. I'm using the websockets library, and my server looks like this:
#!/usr/bin/env python3
import asyncio
import websockets
from logging import getLogger, INFO, StreamHandler
logger = getLogger('websockets')
logger.setLevel(INFO)
logger.addHandler(StreamHandler())
clients = set()
async def handler(websocket, path):
global clients
clients.add(websocket)
try:
await asyncio.wait([ws.send("Hello!") for ws in clients])
await asyncio.sleep(10)
finally:
clients.remove(websocket)
start_server = websockets.serve(handler, host='127.0.0.1', port=6969)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
and the client looks like this:
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="UTF-8">
<title>Chat</title>
</head>
<body style="margin:0">
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:6969/");
var messages = document.getElementById('messages');
ws.onmessage = function (event) {
var messages = document.getElementById('messages');
var message = document.createElement('li');
var content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
</script>
Messages:
<ul id="messages"><li>Hello!</li></ul>
</body></html>
So the issue is that the client above works fine, until I run the server on my Ubuntu machine (and I've made sure to forward port 6969 to that machine) and try to connect over the internet. Hostname resolution is working fine, because I can ssh in to start the server, but trying to connect to the websocket always shows me the error message:
Firefox can’t establish a connection to the server at ws://<remote server url>:6969/.
or similiar for other browsers. Also, in case anyone was wondering, the logger isn't outputting anything useful (since the connection is failing the server isn't doing anything).
Your line:
websockets.serve(handler, host='127.0.0.1', port=6969)
provides a specific address on which the websockets server listens. Your server will only listen on that address; any requests to any other address will never be seen.
From https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.create_server :
The host parameter can be a string, in that case the TCP server is bound to host and port. The host parameter can also be a sequence of strings and in that case the TCP server is bound to all hosts of the sequence. If host is an empty string or None, all interfaces are assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6).
You have bound your webserver to 127.0.0.1, which is a special address that only ever refers to the local machine. This address is also known as localhost. No other machine can ever connect to your localhost.
The solution is to provide an empty string or None (the default value). In this case, your web server will listen for requests sent to any address.
websockets.serve(handler, port=6969)
Related
I have a vb.net application that opens a socket and listens on it.
I need to communicate via this socket to that application using a javascript running on a browser. That is i need to send some data on this socket so that the app which is listening on this socket can take that data, do some stuff using some remote calls and get some more data and put it back on the socket that my javascript needs to read and print it in the browser.
Ive tried, socket.io, websockify but none have proved to be useful.
Hence the question, is what i am trying even possible? Is there a way that a javascript running in a browser can connect to a tcp socket and send some data and listen on it for some more data response on the socket and print it to the browser.
If this is possible can some one point me in the right direction as to which would help me establish the goal.
As for your problem, currently you will have to depend on XHR or websockets for this.
Currently no popular browser has implemented any such raw sockets api for javascript that lets you create and access raw sockets, but a draft for the implementation of raw sockets api in JavaScript is under-way. Have a look at these links:
http://www.w3.org/TR/raw-sockets/
https://developer.mozilla.org/en-US/docs/Web/API/TCPSocket
Chrome now has support for raw TCP and UDP sockets in its ‘experimental’ APIs. These features are only available for chrome apps and, although documented, are hidden for the moment. Having said that, some developers are already creating interesting projects using it, such as this IRC client.
To access this API, you’ll need to enable the experimental flag in your extension’s manifest. Using sockets is pretty straightforward, for example:
chrome.experimental.socket.create('tcp', '127.0.0.1', 8080, function(socketInfo) {
chrome.experimental.socket.connect(socketInfo.socketId, function (result) {
chrome.experimental.socket.write(socketInfo.socketId, "Hello, world!");
});
});
This will be possible via the navigator interface as shown below:
navigator.tcpPermission.requestPermission({remoteAddress:"127.0.0.1", remotePort:6789}).then(
() => {
// Permission was granted
// Create a new TCP client socket and connect to remote host
var mySocket = new TCPSocket("127.0.0.1", 6789);
// Send data to server
mySocket.writeable.write("Hello World").then(
() => {
// Data sent sucessfully, wait for response
console.log("Data has been sent to server");
mySocket.readable.getReader().read().then(
({ value, done }) => {
if (!done) {
// Response received, log it:
console.log("Data received from server:" + value);
}
// Close the TCP connection
mySocket.close();
}
);
},
e => console.error("Sending error: ", e)
);
}
);
More details are outlined in the w3.org tcp-udp-sockets documentation.
http://raw-sockets.sysapps.org/#interface-tcpsocket
https://www.w3.org/TR/tcp-udp-sockets/
Another alternative is to use Chrome Sockets
Creating connections
chrome.sockets.tcp.create({}, function(createInfo) {
chrome.sockets.tcp.connect(createInfo.socketId,
IP, PORT, onConnectedCallback);
});
Sending data
chrome.sockets.tcp.send(socketId, arrayBuffer, onSentCallback);
Receiving data
chrome.sockets.tcp.onReceive.addListener(function(info) {
if (info.socketId != socketId)
return;
// info.data is an arrayBuffer.
});
You can use also attempt to use HTML5 Web Sockets (Although this is not direct TCP communication):
var connection = new WebSocket('ws://IPAddress:Port');
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
http://www.html5rocks.com/en/tutorials/websockets/basics/
Your server must also be listening with a WebSocket server such as pywebsocket, alternatively you can write your own as outlined at Mozilla
ws2s project is aimed at bring socket to browser-side js. It is a websocket server which transform websocket to socket.
ws2s schematic diagram
code sample:
var socket = new WS2S("wss://ws2s.feling.io/").newSocket()
socket.onReady = () => {
socket.connect("feling.io", 80)
socket.send("GET / HTTP/1.1\r\nHost: feling.io\r\nConnection: close\r\n\r\n")
}
socket.onRecv = (data) => {
console.log('onRecv', data)
}
See jsocket. Haven't used it myself. Been more than 3 years since last update (as of 26/6/2014).
* Uses flash :(
From the documentation:
<script type='text/javascript'>
// Host we are connecting to
var host = 'localhost';
// Port we are connecting on
var port = 3000;
var socket = new jSocket();
// When the socket is added the to document
socket.onReady = function(){
socket.connect(host, port);
}
// Connection attempt finished
socket.onConnect = function(success, msg){
if(success){
// Send something to the socket
socket.write('Hello world');
}else{
alert('Connection to the server could not be estabilished: ' + msg);
}
}
socket.onData = function(data){
alert('Received from socket: '+data);
}
// Setup our socket in the div with the id="socket"
socket.setup('mySocket');
</script>
In order to achieve what you want, you would have to write two applications (in either Java or Python, for example):
Bridge app that sits on the client's machine and can deal with both TCP/IP sockets and WebSockets. It will interact with the TCP/IP socket in question.
Server-side app (such as a JSP/Servlet WAR) that can talk WebSockets. It includes at least one HTML page (including server-side processing code if need be) to be accessed by a browser.
It should work like this
The Bridge will open a WS connection to the web app (because a server can't connect to a client).
The Web app will ask the client to identify itself
The bridge client sends some ID information to the server, which stores it in order to identify the bridge.
The browser-viewable page connects to the WS server using JS.
Repeat step 3, but for the JS-based page
The JS-based page sends a command to the server, including to which bridge it must go.
The server forwards the command to the bridge.
The bridge opens a TCP/IP socket and interacts with it (sends a message, gets a response).
The Bridge sends a response to the server through the WS
The WS forwards the response to the browser-viewable page
The JS processes the response and reacts accordingly
Repeat until either client disconnects/unloads
Note 1: The above steps are a vast simplification and do not include information about error handling and keepAlive requests, in the event that either client disconnects prematurely or the server needs to inform clients that it is shutting down/restarting.
Note 2: Depending on your needs, it might be possible to merge these components into one if the TCP/IP socket server in question (to which the bridge talks) is on the same machine as the server app.
The solution you are really looking for is web sockets. However, the chromium project has developed some new technologies that are direct TCP connections TCP chromium
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.
I created simple app to start with socket.io, but when I run it, Chrome(tested in other browsers, result same) eats all of my CPU and makes many requests:
I'm new to sockets, but I'm sure this is not how it should work. The code running in browser is really simple, it should just connect to socket and log all received data to console:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.2.0.js" charset="UTF-8"></script>
</head>
<body>
<script type="application/javascript">
var Sockets = io.connect('http://localhost:4000');
Sockets.on('Test', function (data) {
console.log(data);
});
</script>
</body>
</html>
Also, my server file looks like this:
server.js
var app = require('express')();
var http = require('http').Server(app);
var bodyParser = require("body-parser");
var io = require('socket.io')(http);
var port = 4000;
http.listen(port, function () {
console.log('Server running at port ' + port);
});
var urlencodedParser = bodyParser.urlencoded({extended: false});
app.post('/', urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
var post = req.body;
io.emit("Test", post.data);
console.log(post.data);
res.send('true');
});
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
When I run the server node server.js, I got the Server running at port 4000 message and everything seems fine. But when I open the index.html in my browser, the node console is spammed by a user connected messages. Instead of connecting one client, the browser makes dozens of requests every second. When I close the browser, there is no output for some time, and then the node console is spammed by user disconnected messages.
This server should redirect all data sent via POST to connected sockets. When I make this POST request, the node server receives it (I know because it print's it into node console). But it's not received by the socket client, as there is no output in browser console (but the browser still makes dozens of new connections every second.
What is wrong here? First I thought I just messed up, so I went back and copy-pasted code from tutorial I found (not in English, but in Czech), but nothing changed. The tutorial has a lot of positive feedback, so there is propably something wrong with my computer. But what?
I had experienced the same issue, by following an example where the client was using the source of socket.io from this cdn: https://cdn.socket.io/socket.io-1.2.0.js
Tons of clients created whenever I tried to run the file (no matter if i just double clicked the html file, or if I put it under a web server, like IIS) . I then realized it might be an older version, and I just took the latest one released from this source: https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js
Everything works fine now.
Hope this helps
So to find what exactly was wrong, I downloaded example socket chat from socket.io website. When I runned it, I experienced exactly the same wrong behaviour - browser is opening many socket connections every second instead of keeping one.
So I deleted node_modules folder and used npm to install these modules again and whoa, it worked. So propably the files just corrupted during download or whatever it was, but doing the same procedure again was working this time.
Your configuration of running that page from a different web server than your socket.io server is on won't work as you have it. It will take one of three changes to make it work:
You can use the "same origin" for the web page and the socket.io connection by loading the web page from the same server that your socket.io. That means you need to load the web page directly from your socket.io web server.
You can configure your socket.io web server to accept cross origin connections (CORS connections).
You can configure your socket.io client to connect directly using webSocket without doing socket.io's usual preview with a regular http request.
If you're testing something you intend to deploy for real, you may as well just make your existing socket.io web server server your web page and load the web page directly from that.
Another possible cause of a situation like this is an incompatible client and server version of socket.io. You should make absolutely sure that you have the same version of socket.io on client and server. If you get the client socket.io library from /socket.io/socket.io.js from your socket.io web server, the the client version will automatically always match the server version. The way you are loading it from a CDN, you have to manually make sure you have identical versions.
I have a vb.net application that opens a socket and listens on it.
I need to communicate via this socket to that application using a javascript running on a browser. That is i need to send some data on this socket so that the app which is listening on this socket can take that data, do some stuff using some remote calls and get some more data and put it back on the socket that my javascript needs to read and print it in the browser.
Ive tried, socket.io, websockify but none have proved to be useful.
Hence the question, is what i am trying even possible? Is there a way that a javascript running in a browser can connect to a tcp socket and send some data and listen on it for some more data response on the socket and print it to the browser.
If this is possible can some one point me in the right direction as to which would help me establish the goal.
As for your problem, currently you will have to depend on XHR or websockets for this.
Currently no popular browser has implemented any such raw sockets api for javascript that lets you create and access raw sockets, but a draft for the implementation of raw sockets api in JavaScript is under-way. Have a look at these links:
http://www.w3.org/TR/raw-sockets/
https://developer.mozilla.org/en-US/docs/Web/API/TCPSocket
Chrome now has support for raw TCP and UDP sockets in its ‘experimental’ APIs. These features are only available for chrome apps and, although documented, are hidden for the moment. Having said that, some developers are already creating interesting projects using it, such as this IRC client.
To access this API, you’ll need to enable the experimental flag in your extension’s manifest. Using sockets is pretty straightforward, for example:
chrome.experimental.socket.create('tcp', '127.0.0.1', 8080, function(socketInfo) {
chrome.experimental.socket.connect(socketInfo.socketId, function (result) {
chrome.experimental.socket.write(socketInfo.socketId, "Hello, world!");
});
});
This will be possible via the navigator interface as shown below:
navigator.tcpPermission.requestPermission({remoteAddress:"127.0.0.1", remotePort:6789}).then(
() => {
// Permission was granted
// Create a new TCP client socket and connect to remote host
var mySocket = new TCPSocket("127.0.0.1", 6789);
// Send data to server
mySocket.writeable.write("Hello World").then(
() => {
// Data sent sucessfully, wait for response
console.log("Data has been sent to server");
mySocket.readable.getReader().read().then(
({ value, done }) => {
if (!done) {
// Response received, log it:
console.log("Data received from server:" + value);
}
// Close the TCP connection
mySocket.close();
}
);
},
e => console.error("Sending error: ", e)
);
}
);
More details are outlined in the w3.org tcp-udp-sockets documentation.
http://raw-sockets.sysapps.org/#interface-tcpsocket
https://www.w3.org/TR/tcp-udp-sockets/
Another alternative is to use Chrome Sockets
Creating connections
chrome.sockets.tcp.create({}, function(createInfo) {
chrome.sockets.tcp.connect(createInfo.socketId,
IP, PORT, onConnectedCallback);
});
Sending data
chrome.sockets.tcp.send(socketId, arrayBuffer, onSentCallback);
Receiving data
chrome.sockets.tcp.onReceive.addListener(function(info) {
if (info.socketId != socketId)
return;
// info.data is an arrayBuffer.
});
You can use also attempt to use HTML5 Web Sockets (Although this is not direct TCP communication):
var connection = new WebSocket('ws://IPAddress:Port');
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
http://www.html5rocks.com/en/tutorials/websockets/basics/
Your server must also be listening with a WebSocket server such as pywebsocket, alternatively you can write your own as outlined at Mozilla
ws2s project is aimed at bring socket to browser-side js. It is a websocket server which transform websocket to socket.
ws2s schematic diagram
code sample:
var socket = new WS2S("wss://ws2s.feling.io/").newSocket()
socket.onReady = () => {
socket.connect("feling.io", 80)
socket.send("GET / HTTP/1.1\r\nHost: feling.io\r\nConnection: close\r\n\r\n")
}
socket.onRecv = (data) => {
console.log('onRecv', data)
}
See jsocket. Haven't used it myself. Been more than 3 years since last update (as of 26/6/2014).
* Uses flash :(
From the documentation:
<script type='text/javascript'>
// Host we are connecting to
var host = 'localhost';
// Port we are connecting on
var port = 3000;
var socket = new jSocket();
// When the socket is added the to document
socket.onReady = function(){
socket.connect(host, port);
}
// Connection attempt finished
socket.onConnect = function(success, msg){
if(success){
// Send something to the socket
socket.write('Hello world');
}else{
alert('Connection to the server could not be estabilished: ' + msg);
}
}
socket.onData = function(data){
alert('Received from socket: '+data);
}
// Setup our socket in the div with the id="socket"
socket.setup('mySocket');
</script>
In order to achieve what you want, you would have to write two applications (in either Java or Python, for example):
Bridge app that sits on the client's machine and can deal with both TCP/IP sockets and WebSockets. It will interact with the TCP/IP socket in question.
Server-side app (such as a JSP/Servlet WAR) that can talk WebSockets. It includes at least one HTML page (including server-side processing code if need be) to be accessed by a browser.
It should work like this
The Bridge will open a WS connection to the web app (because a server can't connect to a client).
The Web app will ask the client to identify itself
The bridge client sends some ID information to the server, which stores it in order to identify the bridge.
The browser-viewable page connects to the WS server using JS.
Repeat step 3, but for the JS-based page
The JS-based page sends a command to the server, including to which bridge it must go.
The server forwards the command to the bridge.
The bridge opens a TCP/IP socket and interacts with it (sends a message, gets a response).
The Bridge sends a response to the server through the WS
The WS forwards the response to the browser-viewable page
The JS processes the response and reacts accordingly
Repeat until either client disconnects/unloads
Note 1: The above steps are a vast simplification and do not include information about error handling and keepAlive requests, in the event that either client disconnects prematurely or the server needs to inform clients that it is shutting down/restarting.
Note 2: Depending on your needs, it might be possible to merge these components into one if the TCP/IP socket server in question (to which the bridge talks) is on the same machine as the server app.
The solution you are really looking for is web sockets. However, the chromium project has developed some new technologies that are direct TCP connections TCP chromium
I am using Node.js with socket.io to implement websockets in one of my pages. server.js (what Node.js runs) has this code:
var http = require("http").createServer(),
io = require("socket.io").listen(http);
http.listen(8080);
io.sockets.on("connection", function(socket) {
socket.emit("message", {hello:"world"});
});
And this is the code I'm trying to connect with:
var socket = new WebSocket("ws://92.60.122.235:8080/");
socket.onopen = function() {
alert("Socket has been opened!");
}
When I load the page, nothing happens. I'm using Chrome, and I know websockets are supported. No errors are present in the error console, and if I watch socket.io serving requests from command line I don't see any user connecting.
As far as I know this should work, could anyone explain what could be going wrong?
You need a socket.io client to pass some authentication phases I believe. Try this, and it should work(the client javascript is served by socket.io itself, don't worry about it).
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('message', function (data) {
console.log(data);
socket.emit('helloworld', { msg: 'why do you so love to say hello world?' });
});
</script>
From http://socket.io/#faq
Why not just call it WebSocket if the actual WebSocket is not
present and mimick its API?
Socket.IO does more than WebSocket, even
if WebSocket is selected as the transport and the user is browsing
your website with an ultra modern browser. Certain features like
heartbeats, timeouts and disconnection support are vital to realtime
applications but are not provided by the WebSocket API out of the box.
This is akin to jQuery's decision of creating a feature-rich and
simple $.ajax API as opposed to normalizing XMLHttpRequest.
You can download the webpage source code that runs in Chrome, Firefox, and IE (at least) via the blog article "Websocket Server Demonstration" from the High Level Logic Project. The webpage is set up for developers.