I need to delay when the handshake starts when using the WebSocket API on the browser.
The server is a Nucleo board (L476RG) with a wifi shield IDW01M1.
The client is Firefox v50.1
1. Testing the server
I made Python scripts to establish a WebSocket connection. I noticed that I needed to first "Connect" to the server. Then initiate the exchange after a delay of 600ms
I cannot run my server faster than this. Remember this is a hobby level MCU
2. Testing the client
I made a local server using Python. My Javascript client connects to it with no issues.
#!c:/Python27/python.exe -u
import socket
import time
TCP_IP = '172.24.220.1'
TCP_PORT = 3000
BUFFER_SIZE = 1024
#
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect first
connected = False
while not connected:
try:
s.connect((TCP_IP, TCP_PORT))
connected = True
except Exception as e:
pass
#------------------------------------
time.sleep(0.6)
#------------------------------------
# Send first bytes
s.send("Good-hi")
# Ping pong
data = s.recv(BUFFER_SIZE)
Same issue happens with Python also when using the WebSocket library
#!c:/Python27/python.exe -u
import time
import websocket
from websocket import create_connection
remote = "ws://172.24.220.1:3000"
websocket.enableTrace(True)
ws = websocket.WebSocket()
ws.connect(remote) #<------Need to add delay inside this method
print "WebSocket established"
ws.close()
This page explains what happens inside the WebSocket method.
With Python I can open a socket without any handshake (RAW Socket), then start my handshake by sending manually the headers.
However this is impossible to do in a browser because I can't open RAW sockets.
At least, this is my understanding so far.
Summary, is there a way to first establish a connection between client and server, then start the handshake at will ?
If you use the WebSockets api in javascript.
There is a onopen event that gets fired when the connection is ready.
you could put a setTimeout inside this to delay sending first data.
I don't think you can delay the handshake itself.
Maybe try putting new Websocket inside setTimeout to make sure all files have been served before trying to start connection.
more info here:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
Related
I have created a flask website with python. Now, I'm trying to implement some WebRTC/PeerToPeer functionality. I have managed to connect the two peers by manually copy/pasting the SDP back and forth between them using input fields. Everything is working as supposed.
In stead of manually copy/pasting the SDP back and forth, I want to send the SDP through a websocket from the (vanilla) javascript client side to the python backend. However, this is causing me some issues.
I'm not sure I totally understand how the communication between sockets work (I'm fairly new in that field). The code below is my python server.
import socket
import threading
HEADER = 8192
PORT = 3000
SERVER = '{PRIVATE IP ADDRESS}'
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!DISCONNECT'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f'[NEW CONNECTION] {addr} connected.')
connected = True
while connected:
msg = conn.recv(HEADER)
print(f'[{addr}] {msg}')
conn.close()
def start():
server.listen()
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f'[ACTIVE CONNECTIONS] {threading.activeCount() - 1}')
if threading.activeCount() - 1 == 0:
break
start()
In the javascript on the client side, all I do is initialize the websocket using the same IP and port as the server is running on. When I refresh the client html page in the browser, the client socket is sending a message to the server. However, I'm not able to decode this message with utf-8 because of a wrong startbyte or something. I have read that sockets might use different protocols. Does that have anything to say in this case? Also, the javascript websocket never changes readystate from 0 to 1, so it never actually connects.
Am I missing something? Is there an easier or better way to connect the javascript client with the python server?
I have a socket server running with netty-socketio and a web app that connects to it using socket.io-client JS library.
The problem is that I'm losing a few connections (not all, let's say 20%).
For the lost connections: right after the connection is made by the client, the server logs client did not complete upgrade - closing transport and disconnects the client.
This happens on my production server (using nginx as proxy) and also on my local environment (connecting directly to the netty-socketio server). It's pretty much random and I cant identify a pattern on it. For example, if I continuously keep refreshing the client app on the browser (with a 5 seconds interval), at some point this error will happen, and for the subsequent tries it will work normal again (until it happens another time).
This is the error on the netty-socketio lib: https://github.com/mrniko/netty-socketio/blob/master/src/main/java/com/corundumstudio/socketio/transport/WebSocketTransport.java#L196
but I could not figure out why it happens randomly (some times at the first try)
Any thoughts on this are really appreciated.
Thanks
After some research and tests I found out that when using netty-socketio as server, you need to specify the transport method on the client side.
var socket = io('server-address', { transports: [ 'polling' ] });
// or
var socket = io('server-address', { transports: [ 'websocket' ] });
If you don't specify it, the connection will be established using polling as transport method and netty will automatically try to upgrade it to websocket. This is what was causing connection failures.
After specifying the transport method I had 0% connection failures so far.
My client is connecting to socket server using socket.io 1.0+ lib as:
$scope.socket = io.connect( "/gateway" );
On server side I launch express server and socket server attached as:
httpServer = http.createServer( app ).listen( process.env.PORT, process.env.IP || "0.0.0.0", function() {
io = require( 'socket.io' )( httpServer ).of("/gateway");
io.on('connection', function( socket ) {
// socket events here
}
});
Then the project is tested on heroku. What bother me a lot is this screen from chrome dev tools
You can see there that constantly 2 polling requests are being performed. One gets response in couple of milliseconds, other one takes somewhere around 26 seconds. If I click on one of them I could see that the real difference between them is request method: the one that uses POST gets quick response, the one uses GET remains in pending state until gets response (or timeout) after ~26 seconds.
In my development enviromnent (c9.io) I do not see this behaviour, but in testing (heroku free node) I get this.
Probably because of this I get some other weird behaviour only on heroku, for example on tab close I do not receive a disconnect event, while on c9 I do..
Has anybody faced the same problem? Is there a fix?
As it turns out the long response was mistreated to a visible open connection when polling transport is being used. In this case a 25 second connection is being held open for client-server communication. It is normal, although you have to know about it - some logging modules/solutions may treat it as long response and constantly warn you.
In short
if the sebsocket transport is used there will be one websocket connection open all the time
is the polling transport is used, then every 25-26 seconds a new GET connection will be (re)established.
I am using socket.io.Some users sending message to me 'I can't send a message why ?'.I researched this problem,guess firewall or antivirus blocking websocket.If browser doesn't support the websocket,socket.io automatically switching to xhr polling,there is no problem.But If browser supports the websocket and antivirus or firewall is blocking the websocket,socket.io is not switching to xhr,and users can't send messages.How can I resolve this problem ?
Here is a websocket test report a user
http://websocketstest.com/result/244711
Websocket support is ok,data receive is no.
You can set Socket.IO to use only XHR polling in the configuration:
io.configure(function () {
io.set("transports", ["xhr-polling"]);
});
See Configuring Socket.IO in the official documentation.
I have found that a lot of users end up not being able to connect successfully with socket.io. Rather than trying to continually diagnose it, I have started to build my apps to have easy fallbacks to ajax. I can in fact, change my environment variable of useSocketIO to false, and the whole site, chatting, tipping, image sharing will fallback to ajax. This does not solve the underlying issue, but has saved me a lot of headaches in lost data not being transmitted.
pseudo code on the client
# check that I have a socket object
if socket != null
# if not connected, try to reconnect
if !socket.connected and !socket.connecting
attemptResetOfSocketIO()
# if now connected, send socket message
if socket.connected or socket.connecting
sendSocketMessage()
else
# not connected, send via ajax
sendAjaxMessage()
else
# no socket object, send via ajax
sendAjaxMessage()
I'm trying to use node.js as a server with socket.io (over a https connection server object, client connecting with option secure: true) with a JavaScript front end.
On the server if a login attempt fails I am calling:
socket.emit('unauthorized');
socket.disconnect();
On the client side I have:
this.Socket = io.connect(server, { secure: true });
this.Socket.on('disconnect', this.Socket_Disconnect);
this.Socket.on('unauthorized', this.Socket_Unauthorized);
I am able to see the disconnect event firing (with arguments set as ['booted'] regardless of whether i pass any arguments to socket.disconnect(), but the unauthorized event never makes it. Am I attempting to pass this message the wrong way?
The rationale I have here is that I want to be able to send different types of disconnect events like:
logout - clients should stop trying to connect until a user logs in
server reboot - clients should reattempt connection until they get through
I need to be able to tell on the client side why a client was disconnected by the server, is there at least some way to make sure a message has sent before calling socket.disconnect()?
Edit: this appears specific to the node.js cluster code - when the application is run on a single thread it works as expected.
Solved this by setting up a Redis server and configuring socket.io to use it within node.js if anyone finds this looking for a solution to the issue.