How to use Websockets with Pyramid and socket.io? - javascript

I'm trying to create a simple WebSocket application using Pyramid and socket.io frameworks.
Server-side code:
from pyramid.response import Response
from pyramid_socketio.io import SocketIOContext, socketio_manage
import gevent
def includeme(config):
'''
This method is called on the application startup.
'''
config.add_route('socket.io', 'socket.io/*remaining')
class ConnectIOContext(SocketIOContext):
# self.io is the Socket.IO socket
# self.request is the request
def msg_connect(self, msg):
print "Connect message received", msg
self.msg("connected", hello="world")
# Socket.IO implementation
#view_config(route_name="socket.io")
def socketio_service(request):
print "Socket.IO request running"
print request
retval = socketio_manage(ConnectIOContext(request))
return Response(retval)
Client code:
<script>
var socket = null;
$(document).ready(function() {
socket = new io.Socket(null, null);
socket.on('connect', function() {
console.log("Connected");
socket.send({type: "connect", userid: 123});
});
socket.on('message', function(obj) {
console.log("Message received");
console.log("Message", JSON.stringify(obj));
if (obj.type == "some") {
console.log("do some");
}
});
socket.on('error', function(obj) {
console.log("Error", JSON.stringify(obj));
});
socket.on('disconnect', function() {
console.log("Disconnected");
});
console.log("Connecting...");
socket.connect();
});
</script>
I need this code to use web-sockets for the connection, but it falls back to XHR-polling.
How can I fix it?
Thanks in advance, Ivan.

You probably want to look at the latest release of gevent-socketio, and its documentation at http://gevent-socketio.readthedocs.org/
A major overhaul was done at the PyCon 2012 sprints, by John Anderson, Sébastien Béal and myself.

You may also have a look at pyramid_sockjs. It integrates well with Pyramid and uses sockjs that fulfills the same role of socket.io and is arguably simpler to understand.

Related

Using Socket.IO from Node.js to connect to external server

Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.
I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.
Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.
var myemail = "email#gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.
var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables
var myemail = "email#gmail.com";
var device_id = '12345';
var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');
//Connect listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
Any ideas?
UPDATE
Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).
debugging output image link
Solved this - issue was that the server I was connecting to required use of https, so I needed to add
{secure: true, rejectUnauthorized: false}
after the url to connect to.
Full working example:
const myemail = email#email.com;
const device_id = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true, rejectUnauthorized: false});
function doStuff(){
//Listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "003021");
}
doStuff();
I think the line causing the issue is :
var socket = io.connect('https://example.net:3000');
I managed to make a working example using this code :
const myemail = "email#gmail.com";
const device_id = '12345';
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
try{
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
}catch(e){ console.log(e); }
});

Socket.IO not using fallback methods

I have a node server that's running a socket.io server and a client to work with it. Simple story, I need to be able to transfer messages between the two. This is working as intended in browsers that support web sockets but when a fallback method needs to be used its not working.
I should mention that pages are served from an apache server and the node server is only used for a specific page. The code that I am using is below, I've tinkered on this for a while and can't figure out how to fix it.
Also worth mentioning that when the page is opened in IE9(websockets not supported),
logging connection.io.engine.transport.name would give "websocket".
Client:
connection = io(window.location.protocol + '//localhost:8888', {
'reconnect': false,
'max reconnection attempts': 0,
'transports':
[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]
});
connection.on('connect',function () {
console.log("Socket is open");
$('#dc-status').hide();
connection.emit('message',JSON.stringify(info));
connection.on('message',function (e) {
//DO SOMETHING WITH THE DATA RECIEVED
});
});
Server:
var ioserver = require('socket.io');
var io = ioserver.listen(8888);
var http = require("http");
console.log("server started...");
io.set('transports',[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);
io.sockets.on('connection', function(ws) {
var req;
var order;
var courier;
var after;
var session;
var options = {};
console.log("New client connected");
// console.log("Transport: " + io.transports[ws.id].name);
ws.on('message', function(data) {
//WORK WITH THE DATA RECEIVED
//NOT RELEVANT TO EXAMPLE
console.log('received: %s', data);
parsedData = JSON.parse(data);
});
ws.on('disconnect', function () {
console.log("Connection closed");
});
});
Ok, so after much struggle with this I have found a solution for making sockets work in old browsers.
As of version 1.0 Socket.io uses Engine.io instead of fallback methods, which takes care of transports.
To get a working solution I skipped using the Socket.io layer and used just Engine.io instead.
In the client you have something like
var connection = eio.Socket('host-address');
and then you just bind the regular events(e.g message, close).
And in the server part instead of require('Socket.IO'), you call require('Engine.IO'), example:
var engineio = require('engine.io');
var wss = engineio.listen(10101);
The binding is the same.

Connect two clients in websocket with PyWebSocket

i am new to websocket using pywebsocket, basically trying to create a simple chat application with websocket and pywebsocket.
Until now i am done with following script
if ("WebSocket" in window)
{
//alert("WebSocket is supported by your Browser!");
// Let us open a web socket
var ws = new WebSocket("ws://192.168.1.3:9998/echo");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
console.log("Channel opened");
//ws.send("Message to send");
//alert("Message is sent...");
//console.log("Message is sent...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
//alert("Message is received..."+received_msg);
console.log("message : "+received_msg);
};
ws.onclose = function()
{
// websocket is closed.
//alert("Connection is closed...");
console.log("connection closed");
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
function sendmessage(){
msg=document.getElementById("chat").value;
console.log(msg);
ws.send(msg);
document.getElementById("chat").value="";
}
Now the problem is the messages that are sent are echoed to the system itself, if another client connect to same channel its messages are echoed to itself, they are sent to another client which is connected with same channel.
pywebsocket is initialized as follows
python standalone.py -p 9998 -w ../example/
So how can i connect two system and allow chat.
Thanks in advance
Not sure, but if you want to broadcast any received message (sent by any connected client) to all other currently connected clients, that is not "echo" .. but "broadcast".
Here is an example using AutobahnPython.
Disclosure: I am original author of Autobahn and work for Tavendo.

Node JS push server send/receive

I am trying to set up a node js server to do push notifications to my browser app. I have a basic example working, but I am wondering how to send data up to the server from the client on handshake.
I Need to send to the server something like a user id, so when a notification comes in for them, it can be routed back to the user.
my server looks something like this
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs');
app.listen(8000);
function handler ( req, res ) {
res.writeHead( 200 );
res.end('node working');
};
io.sockets.on( 'connection', function ( socket ) {
socket.volatile.emit( 'notification' , "blah" );
});
and my client looks something like this
var socket = io.connect('http://localhost:8000');
socket.on('notification', function (data) {
//prints data here
});
In socket.io, the emit is essentially like any other event handler (e.g. jQuery's .on('click'...)); you declare the event and send the data. On the server, you add the .on('event', ...) to catch the request and process it.
The socket.io front page shows this example for the server:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
And this for the client:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
It sounds like the part you're looking for is the socket.emit portion.
I have done this sort of thing in the past by setting a cookie on the client (which you're probably doing anyway), and then using socket.io's authorization event. You can use this event to decide whether to even accept the socket connection to the user in the first place.
io.configure(function () {
io.set('authorization', function (handshakeData, callback) {
var cookie = handshakeData.headers.cookie;
// parse the cookie to get user data...
// second argument to the callback decides whether to authorize the client
callback(null, true);
});
});
See more documentation here: https://github.com/LearnBoost/socket.io/wiki/Authorizing
Note that handshakeData.headers.cookie is just a string literal representation of the cookie, so you'll have to do your own parsing.

Socket IO reconnect?

How to reconnect to socket io once disconnect has been called?
Here's the code
function initSocket(__bool){
if(__bool == true){
socket = io.connect('http://xxx.xxx.xxx.xxx:8081', {secure:false});
socket.on('connect', function(){console.log('connected')});
socket.on('disconnect', function (){console.log('disconnected')});
}else{
socket.disconnect();
socket = null;
}
}
If I do initSocket(true), it works. If I do initSocket(false), it disconnects. BUT THEN if I try to reconnect using initSocket(true), the connection does not work anymore. How can I get the connection to work?
Well, you have an option here ...
The first time you initialize the socket value you should connect with io.connect,
The next time ( after you've called disconnect once ), you should connect back with socket.socket.connect().
So your initSocket, should be something like
function initSocket(__bool){
if(__bool){
if ( !socket ) {
socket = io.connect('http://xxx.xxx.xxx.xxx:8081', {secure:false});
socket.on('connect', function(){console.log('connected')});
socket.on('disconnect', function (){console.log('disconnected')});
} else {
socket.socket.connect(); // Yep, socket.socket ( 2 times )
}
}else{
socket.disconnect();
// socket = null; <<< We don't need this anymore
}
}
I know you already have an answer, but I arrived here because the socket.IO client reconnection feature is broken in node at the moment.
Active bugs on the github repo show that lots of people aren't getting events on connect failure, and reconnect isn't happening automatically.
To work around this, you can create a manual reconnect loop as follows:
var socketClient = socketioClient.connect(socketHost)
var tryReconnect = function(){
if (socketClient.socket.connected === false &&
socketClient.socket.connecting === false) {
// use a connect() or reconnect() here if you want
socketClient.socket.connect()
}
}
var intervalID = setInterval(tryReconnect, 2000)
socketClient.on('connect', function () {
// once client connects, clear the reconnection interval function
clearInterval(intervalID)
//... do other stuff
})
You can reconnect by following client side config.
// 0.9 socket.io version
io.connect(SERVER_IP,{'force new connection':true });
// 1.0 socket.io version
io.connect(SERVER_IP,{'forceNew':true });
This is an old question, but I was struggling with this recently and stumbled here. Most recent versions of socket.io (>2.0) doesn't have the socket.socket property anymore as pointed out here.
I am using socket.io-client 2.2.0 and I was facing a situation where the socket seems to be connected (property socket.connected = true) but it wasn't communicating with the server.
So, to fix that, my solution was call socket.close()and socket.open. These commands force a disconnection and a new connection.
I had an issue with socket-io reconnect. May be this case will help someone. I had code like this:
var io = require('socket.io').listen(8080);
DB.connect(function () {
io.sockets.on('connection', function (socket) {
initSockets(socket);
});
});
this is wrong, becase there is a delay between open port assigned callbacks. Some of messages may be lost before DB gets initialized. The right way to fix it is:
var io = null;
DB.connect(function () {
io = require('socket.io').listen(8080);
io.sockets.on('connection', function (socket) {
console.log("On connection");
initSockets(socket);
});
});

Categories