User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Websockets (How To Use Them) was, (closes immediately)

Thu Jul 02, 2015 9:43 pm

Hi;

I have recently installed Apache2 and have just installed Tornado, I am following a couple of guides and have just created a simple websocket python script and associated index.html page.

As soon as I navigate to the IP address of my webserver on the Pi I receive a popup message (which is generated from the index.html page saying connection closed!!

This happens in Google Chrome and Safari, what have I done wrong?

Here is the server script:

Code: Select all

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web

class WSHandler(tornado.websocket.WebSocketHandler):

	def open(self):
		print 'user is connected.\n'

	def on_message(self, message):
		print 'received message: %s\n' %message
		self.write_message(message + ' OK')

	def on_close(self):
		print 'connection closed\n'

application = tornado.web.Application([(r'/ws', WSHandler),])

if __name__ == "__main__":
	http_server = tornado.httpserver.HTTPServer(application)
	http_server.listen(8888)
	tornado.ioloop.IOLoop.instance().start()
And here is the index.html page:

Code: Select all

<!doctype html> 
<html>
<head>
<title>Websocket</title>
<script src="http://code.jquery.com/jquery-2.0.0.js"></script>
</head>
<body>
<h1>Websocket</h1>
<label id="conn_text"></label><br />
<input type="text" id="input_text"/>
<input type="submit" id="button" value="Send" /><br />
<div id="messages_txt" />
<script>
  $(document).ready(function () {
    //change example.com with your IP or your host
    var ws = new WebSocket("ws://localhost:8888/ws");
    ws.onopen = function(evt) {
      var conn_status = document.getElementById('conn_text');
      conn_status.innerHTML = "Connection status: Connected!"
    };
    ws.onmessage = function(evt) {
      var newMessage = document.createElement('p');
      newMessage.textContent = "Server: " + evt.data;
      document.getElementById('messages_txt').appendChild(newMessage);
    };
    ws.onclose = function(evt) {
      alert ("Connection closed");
    };
    $("#button").click(function(evt) {
      evt.preventDefault();
      var message = $("#input_text").val();
      ws.send(message);
      var newMessage = document.createElement('p');
      newMessage.textContent = "Client: " + message;
      document.getElementById('messages_txt').appendChild(newMessage);
    });
  });
</script>
</body></html>
Last edited by JonnyAlpha on Fri Jul 03, 2015 7:06 pm, edited 2 times in total.
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

ame
Posts: 3172
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Websocket closes immediately

Thu Jul 02, 2015 11:54 pm

That's how it works. Web browsing uses very short transactions for each request. Open a socket, get some data, close the socket. The sockets are not kept open for the whole session. I think that is what you are seeing here.

Heater
Posts: 16091
Joined: Tue Jul 17, 2012 3:02 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 4:35 am

ame,

No. That is not how it works with websockets.

The whole idea of websockets is that the JS in the page opens a connection back to the server which remains open as long as the page is open.

That way the server can "push" data in real time down to the browser without the browser having to poll for it.

I have no idea how this works with apache and Python. It is very easy to do with node.js and the socket.io library.
https://nodejs.org/
http://socket.io/

One can continue to have ones web pages served up by Apache with PHP, Python or whatever, and create a little webserver in node.js that operates on a different port number and serves up the websocket connections.
Last edited by Heater on Fri Jul 03, 2015 8:39 am, edited 1 time in total.
Memory in C++ is a leaky abstraction .

User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 4:43 am

So delete the url for jQuery and insert the url you have suppiled for node.is in my index.html.
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

Heater
Posts: 16091
Joined: Tue Jul 17, 2012 3:02 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 8:46 am

JonnyAlpha,

No. I meant to go to those links and read them.

The front page of nodejs.org shows how to create a web server in node in a handful of lines of code that you can run from the command line and serves up "hello world" to any visiting browser.

The socket.io site shows how to set up a websocket between your web server and the browser page. Again in a handful of lines of code.

Then add your own code around that, in both the browser and the server to exchange whatever data it is you want and display it how you like.

Sorry I forgot one more link to get you started https://learn.adafruit.com/node-embedde ... ode-dot-js. Adafruit has a lot of noice node tutorial stuff on pages linked from there.

P.S. You can continue to use jQuery in your page if you like.
Memory in C++ is a leaky abstraction .

User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 12:16 pm

Heater wrote:JonnyAlpha,

No. I meant to go to those links and read them.

The front page of nodejs.org shows how to create a web server in node in a handful of lines of code that you can run from the command line and serves up "hello world" to any visiting browser.

The socket.io site shows how to set up a websocket between your web server and the browser page. Again in a handful of lines of code.

Then add your own code around that, in both the browser and the server to exchange whatever data it is you want and display it how you like.

Sorry I forgot one more link to get you started https://learn.adafruit.com/node-embedde ... ode-dot-js. Adafruit has a lot of noice node tutorial stuff on pages linked from there.

P.S. You can continue to use jQuery in your page if you like.
Heater;

Many thanks for the steer, I have spent this morning going through the chat example for socket.io and I am starting to get a better understanding of how websockets work.
I have successfully set up a working index.html / index.js / pack.json but I have a long way to go, to driving motors, especially over a serial link to an Arduino :-)

I have also looked at some LED scripts and node-serial for talking to serial connected devices.
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: Websocket closes immediately

Fri Jul 03, 2015 1:03 pm

damn, this is so nice!
but let me understand one thing: i was looking to a webpage speaking about a websocket server in php (this: http://www.sanwebe.com/2013/05/chat-usi ... php-socket ) and i can't understand why do i need a separate php process running? i have apache and php installed, is this a limit of apache? i really don't want another process :(
is there any hope that a webserver can manage also this? :)

Heater
Posts: 16091
Joined: Tue Jul 17, 2012 3:02 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 3:05 pm

Massi,

To be honest it's not clear to me what you can do with Apache now a days.

Traditionally HTTP was a request/response protocol. The browser opens a connection to a server then sends a HTTP request for whatever page. The server responds with an HTTP response containing the HTML or the page in its payload. The connection is then closed.

Now we have websockets where the socket connection is started with a similar HTTP request but then the connection is "upgraded" to the websocket protocol. That is a two way stream of data that stays open until one end decides to close it.

As such a websocket connection requires a long running process on the server to keep the socket open. That is what node.js with socket,io does and what that PHP thing does as well.

Perhaps Apache has a way to handle this long term connect today. I don't know. It has been so easy to do these things with node.js that I'm not inclined to find out.

As I said one can continue to serve static pages or PHP generated pages via Apache, and just add that second server process in node or PHP to handle the web sockets.

However what I'm doing currently is using node to do all the regular web serving as well. No need for Apache or PHP and we are back to a single self contained process. Whic gives us all the useful node modules for handling serial ports, GPIO, etc on the Pi as well. Sweet!

One commonly uses the espress.io node module to make serving up web page a lot easier easier. http://expressjs.com/
Memory in C++ is a leaky abstraction .

User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Re: Websocket closes immediately

Fri Jul 03, 2015 7:08 pm

Massi wrote:damn, this is so nice!
but let me understand one thing: i was looking to a webpage speaking about a websocket server in php (this: http://www.sanwebe.com/2013/05/chat-usi ... php-socket ) and i can't understand why do i need a separate php process running? i have apache and php installed, is this a limit of apache? i really don't want another process :(
is there any hope that a webserver can manage also this? :)
It sure is nice but I am still struggling :-)
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Re: Websockets (How To Use Them) was, (closes immediately)

Fri Jul 03, 2015 7:13 pm

Well I have spent nearly all day on this and have a better understanding of how it works and although I managed to get through the 'Chat' example on the socket.io page (without copy and pasting) I am still completely clueless as to how to progress to:

(a) - Turning and LED or Motor on and off using websockets.
(b) - Expanding the above to interface an Arduino using pyserial?

Whilst there are lots of examples, none of them do exactly what, each one has an element of what I need but they all do it subtly differently and I am struggling to put it all together.
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

User avatar
JonnyAlpha
Raspberry Pi Certified Educator
Raspberry Pi Certified Educator
Posts: 572
Joined: Sat Nov 02, 2013 2:06 pm

Re: Websockets (How To Use Them) was, (closes immediately)

Fri Jul 03, 2015 8:20 pm

So far I have this working version of the chat example.
I have added a button on the web page (that much I can do), but how do I go about creating a socket to recieve data from index.html and send it to the Pi?

index.html

Code: Select all

<!doctype html>
<html>
  <head>
    <title>Socket.IO Chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helevetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
    <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
      </form>

	<button id ="ledon" type="button">
		LED ON
	</button>
      <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
      <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
      <script>
	 var socket = io();
         $('form').submit(function(){
	   socket.emit('chat message', $('#m').val());
	   $('#m').val('');
	   return false;
	});
      </script>
  </body>
</html>	
index.js

Code: Select all

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
 res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
  console.log('message: ' + msg);
});
  socket.on('disconnect', function(){
   console.log('user disconnected');
  });
});
http.listen(3000, function(){
 console.log('Listening on *:3000');
});
package.json

Code: Select all

{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "desciption": "my first socket.io.app",
  "dependencies": {
    "express": "^4.10.2",
    "socket.io": "^1.3.5"
  }
}
Understanding how the package.json folder fits in is pretty complicated and it takes forever to build it using the npm installs.
Raspberry Pi Certified Educator. Main Hardware - Raspberry Pi 1 model B revision 2, Raspberry Pi 2 model B, Pi Camera

Heater
Posts: 16091
Joined: Tue Jul 17, 2012 3:02 pm

Re: Websockets (How To Use Them) was, (closes immediately)

Fri Jul 03, 2015 9:10 pm

I have been working on a kind of demo control panel which is intended to show the status of GPIO pins on the PI via LED indicators on a web page, conversely it sends the state of buttons on the page back to the Pi to drive GPIO outputs. It uses web sockets (socket.io) to do all of this.

Problem is that the scope of this demo got out of hand, it now also includes a chart to draw analog values sent from the Pi, it has a log window to show any text messages from the Pi, it has a terminal window that can be opened to the Pi and even includes a user to user chat window!

Not only that most of this functionality is now broken as I got diverted into rewriting it to use react.js to render the page and that transition is not completed yet.

But, the node.js server part works. Even if the final connection to GPIO and serial is not made yet as I test it on the PC.

Anyway if you are keen the code is here: https://github.com/ZiCog/propanel Perhaps the instructions on that page still work.

The node.js server code is in /src/server.js and the web page serves up and then talks to over web socket is /src/public/index.js

There are other *.jsx files in there you can ignore.
Memory in C++ is a leaky abstraction .

Return to “Other programming languages”