Git Product home page Git Product logo

engine.io-server-java's Introduction

Engine.IO Java

Build Status codecov

This is the Engine.IO Server Library for Java ported from the JavaScript server.

NOTE This library will follow the major version of the JS library starting with version 4.

See also: Socket.IO-server Java, Engine.IO-client Java

Documentation

Complete documentation can be found here.

Installation

If you're looking for the socket.io library instead, please see here.

The latest artifact is available on Maven Central.

Maven

Add the following dependency to your pom.xml.

<dependencies>
  <dependency>
    <groupId>io.socket</groupId>
    <artifactId>engine.io-server</artifactId>
    <version>6.2.1</version>
  </dependency>
</dependencies>

Gradle

Add it as a gradle dependency in build.gradle.

implementation ('io.socket:engine.io-server:6.2.1')

Engine.IO Protocol 1.x suppport

The current version of engine.io-java does not support protocol 1.x.

Usage

If you're looking for the socket.io library instead, please see here.

Usage is slightly different based on the server being used.

Create a servlet to handle the HTTP requests as follows:

public class EngineIoServlet extends HttpServlet {

    private final EngineIoServer mEngineIoServer = new EngineIoServer();

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        mEngineIoServer.handleRequest(request, response);
    }
}

Listen for new connections as follows:

EngineIoServer server;  // server instance
server.on("connection", new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        EngineIoSocket socket = (EngineIoSocket) args[0];
        // Do something with socket like store it somewhere
    }
});

Listen for raw packets received as follows:

EngineIoSocket socket;  // socket received in "connection" event

socket.on("packet", new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        Packet packet = (Packet) args[0];
        // Do something with packet.
    }
});

Listen for messages from the remote client as follows:

EngineIoSocket socket;  // socket received in "connection" event

socket.on("message", new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        Object message = args[0];
        // message can be either String or byte[]
        // Do something with message.
    }
});

Send a packet to client as follows:

EngineIoSocket socket;  // socket received in "connection" event

socket.send(new Packet<>(Packet.MESSAGE, "foo"));

WebSockets

Please see the complete documentation on handling WebSockets here.

Features

This library supports all of the features the JS server does, including events, options and upgrading transport.

License

Apache 2.0

engine.io-server-java's People

Contributors

afkelsall avatar artur- avatar cat9 avatar chenzhang22 avatar dependabot[bot] avatar koush avatar trinopoty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

engine.io-server-java's Issues

continue send http request with transport=polling

does it support socket.io?
when i use socket.io js, it will sent many http request with params such as http://localhost:7070/commonstore-service/gs-guide-websocket/?EIO=3&transport=polling&t=1546595407877-10 (transport is alway polling) and response with 200. then java backend will use up threads.

i also notice there is a project for socket io https://github.com/trinopoty/socket.io-server-java, and i use it ,but the question appears too.

how about to process issue about sent http request continuously?

the html is

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, 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; }
      #messages { margin-bottom: 40px }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
      $(function () {
        var socket = io('http://localhost:7070',{
		  path: '/commonstore-service/gs-guide-websocket/',
		  reconnection: false
		});
        $('form').submit(function(){
          socket.emit('chat message', $('#m').val());
		  $('#messages').append($('<li>').text("send:" + $('#m').val()));
          $('#m').val('');
          return false;
        });
        socket.on('chat message', function(msg){
          $('#messages').append($('<li>').text("receive:" + msg));
          window.scrollTo(0, document.body.scrollHeight);
        });
		
		socket.on('test', function(msg){
          $('#messages').append($('<li>').text("receive:" + msg));
          window.scrollTo(0, document.body.scrollHeight);
        });
		
		socket.on('disconnect', (reason) => {
		  console.log("disconnect for " + reason)
		  $('#messages').append($('<li>').text("disconnect:" + msg));
          window.scrollTo(0, document.body.scrollHeight);
		  if (reason === 'io server disconnect') {
			// the disconnection was initiated by the server, you need to reconnect manually
			socket.connect();
		  }
		  // else the socket will automatically try to reconnect
		});
		
		socket.on('connect', () => {
		  $('#messages').append($('<li>').text("connect:" + msg));
		});
		
		socket.on('error', function(msg){
          $('#messages').append($('<li>').text("error:" + msg));
          window.scrollTo(0, document.body.scrollHeight);
        });
      });
    </script>
  </body>
</html>

java server:

private ConcurrentMap<String,EngineIoSocket> cache=new ConcurrentHashMap<>();
	
	@Bean
	public EngineIoServer socketServer() {
		EngineIoServer engineServer=new EngineIoServer();
		
		engineServer.on("connection", new Emitter.Listener() {
			@Override
			public void call(Object... args) {
				EngineIoSocket socket = (EngineIoSocket) args[0];
				addSocket(socket);
				logger.info("success connection {}",socket.getId());
			}
		});
		
		//new SocketIoServer(engineServer);
		return engineServer;
	}

	protected void addSocket(EngineIoSocket socket) {
		socket.on("message", new Emitter.Listener() {
		    @Override
		    public void call(Object... args) {
		       Object message = args[0];
		       logger.info("success receive message... {}",message);
		    }
		});
		cache.putIfAbsent(UUIDUtils.uuid16(),socket);
	}

Spring Boot dont establish connection with browser using transports: websocket

Hey, I have followed the guide on https://github.com/socketio/engine.io-server-java/blob/master/docs/spring-integration.rst
and have succsfully connected engine.io socket using Node.js application with the following code.

Bean

@Bean
public EngineIoServer engineIoServer(){
    EngineIoServerOptions options = EngineIoServerOptions.newFromDefault();
    options.setAllowedCorsOrigins(null);
    options.setPingTimeout(30000);
    EngineIoServer engineIoServer = new EngineIoServer(options);
    engineIoServer.on("connection", args -> {
        System.out.println("CONNECTION");
    });
    return engineIoServer;
}

Node.js Code

const { Socket } = require('engine.io-client');

const socket = new Socket('http://localhost:4919', {
    transports: ['websocket'],
});

socket.on('open', () => {
    console.log('Connected');    
});

but the same code just for the browser doesnt work.
Browser Code

<script>
    const socket = eio('http://localhost:4919', {
        transports: ['websocket'],
    });

    socket.on('open', function() {
        console.log('open!');
    });
</script>

and we can see that there is no response from the server
image

I have found out that by changing the transports to 'polling' insted of 'websocket' let the browser connect to the server, but I still rather use websocket insted of long polling.

I am using engine.io-server 6.0.1 and Java 17.
the error occured on chrome and edge, didnt check different browsers.

send large base64

Hello !
i'm trying to send base64 ( file size: 1MB ) from javascript( web interface) to engine.io-server-java but socket transport get closed.
when trying to send 260 KB, everything worked fine.

i tried to do some stuff as below:

increasing Header size

   `HttpConfiguration httpConfiguration = new HttpConfiguration();
    logger.info("getRequestHeaderSize "+httpConfiguration.getRequestHeaderSize());
    httpConfiguration.setRequestHeaderSize(bufferSize);
    httpConfiguration.setResponseHeaderSize(bufferSize);
    httpConfiguration.setHeaderCacheSize(65534);
    
   ServerConnector serverConnector = new ServerConnector(mServer, new HttpConnectionFactory(httpConfiguration));
    serverConnector.setHost(ip);
    serverConnector.setPort(port);
    serverConnector.setAcceptedSendBufferSize(bufferSize);
    serverConnector.setAcceptedReceiveBufferSize(bufferSize);
    serverConnector.setIdleTimeout(999999999);`

increasing form content and keys size

 ` ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
    servletContextHandler.setContextPath("/");
    servletContextHandler.addFilter(RemoteAddrFilter.class, "/socket.io/*", EnumSet.of(DispatcherType.REQUEST));
    servletContextHandler.setMaxFormContentSize(bufferSize);
    servletContextHandler.setMaxFormKeys(bufferSize);
    servletContextHandler.setStopTimeout(999999999);`

Please need someone help

Error during WebSocket handshake: Unexpected response code: 400

I have to use engine.io-server-java in my project. When I initiate the eio function, The request has failed and thrown 400 Bad requests. How do I debug this problem? Are there any documents available for engine.io-server-java?

Error

WebSocket connection to 'ws://localhost:8080/engine.io/?EIO=3&transport=websocket&sid=Mg_ZSd5' failed: Error during WebSocket handshake: Unexpected response code: 400
WS.doOpen @ engine.io.js:4403
Transport.open @ engine.io.js:1700
Socket.probe @ engine.io.js:468
Socket.onOpen @ engine.io.js:489
Socket.onHandshake @ engine.io.js:549
Socket.onPacket @ engine.io.js:511
(anonymous) @ engine.io.js:346
Emitter.emit @ engine.io.js:3096
Transport.onPacket @ engine.io.js:1765
callback @ engine.io.js:1510
exports.decodePayload @ engine.io.js:2199
Polling.onData @ engine.io.js:1514
(anonymous) @ engine.io.js:1071
Emitter.emit @ engine.io.js:3096
Request.onData @ engine.io.js:1244
Request.onLoad @ engine.io.js:1311
xhr.onreadystatechange @ engine.io.js:1197

Request Header

Code:

@WebServlet("/engine.io/*")
public class SocketIO extends HttpServlet {
	private final EngineIoServer server = new EngineIoServer();
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        server.handleRequest(request, response);
        server.on("connection", new Emitter.Listener() {
			@Override
			public void call(Object... arg0) {
				System.out.println("Socket connected");			
			}
		});
    }
}

Client Code:

var io = eio("http://localhost:8080", {transport: ["websocket"], upgrade: true, reconnection: false});

can not connect to the engine.io-server-java v1.0.3 using the engine.io-client v3.0.4

The engine.io-client v3.0.4 does not work with the latest version (1.0.3) of the engine.io-server-java.
There is following sentence in the migration notes from 2.x to 3.x:

"due to several breaking changes, a v2 client will not be able to connect to a v3 server (and vice versa)"
https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html

So it looks like engine.io-server-java v1.0.3 in not a v3 server - is there a plan for the upgrade ?

Steps to reproduce:

  1. Below is my client script - in this script I'm using engine.io-client v3.0.4
  2. In the backend I'm using a copy of the io.socket.socketio.server.ServerWrapper from the socket.io-server-test
    Connection is never established - process always exit with code 1.

var io = require('socket.io-client');
var port = process.env.PORT || 3000;

console.log('socket.io port='+port);
var socket = io('http://127.0.0.1:' + port, {
autoConnect: false,
transports: ['websocket']
});
socket.on('connect', function () {
console.log('socket.io connected...')
process.exit(0);
});

socket.on('error', function (err) {
console.log('socket.io error', err);
process.exit(1);
});
socket.connect();

setTimeout(function () {
console.log('socket.io timeout...')
process.exit(1);
}, 20000);

Clarification on XHR polling and handleRequest. Possible bug?

I've ported this fairly easily to a custom HTTP stack on Android. I did have a question around how a http server implementation of the engine.io-server-java is supposed to handle XHR polling and/or long running connections.

By default, it seems that engine.io-server-java gets an xhr request (handleRequest + HttpServletRequest), and immediately responds with NOOP. The client receives this completed request, and immediately sends another XHR poll request, which is then also immediately completed.
This results in the client hitting the server as fast as possible. Hundreds of requests per second. When/if the connection is upgraded to websockets, this hyper polling stops.

By default, it seems engine.io-server-java does not hold the XHR connection until the server needs to send data to the client. Is this intentional?

Currently, my workaround is to delay the handleRequest call with the Java equivalent of a setTimeout(handleReqest, 500). This limits the number of polls per second to 2.

Polling transport malformed request body on large requests

Received this error when sending large text content via polling transport:

WARN  [2021-12-14 09:31:35,188] io.socket.parser.IOParser: An error occured while retrieving data from JSONTokener
! org.json.JSONException: Unterminated string at 7675 [character 7676 line 1]
! at org.json.JSONTokener.syntaxError(JSONTokener.java:507)
! at org.json.JSONTokener.nextString(JSONTokener.java:320)
! at org.json.JSONTokener.nextValue(JSONTokener.java:428)
! at org.json.JSONObject.<init>(JSONObject.java:233)
! at org.json.JSONTokener.nextValue(JSONTokener.java:431)
! at org.json.JSONObject.<init>(JSONObject.java:252)
! at org.json.JSONTokener.nextValue(JSONTokener.java:431)
! at org.json.JSONArray.<init>(JSONArray.java:125)
! at org.json.JSONTokener.nextValue(JSONTokener.java:434)
! at io.socket.parser.IOParser$Decoder.decodeString(IOParser.java:183)
! at io.socket.parser.IOParser$Decoder.add(IOParser.java:92)
! at io.socket.socketio.server.SocketIoClient.lambda$setup$2(SocketIoClient.java:161)
! at io.socket.emitter.Emitter.emit(Emitter.java:123)
! at io.socket.engineio.server.EngineIoSocket.emit(EngineIoSocket.java:185)
! at io.socket.engineio.server.EngineIoSocket.onPacket(EngineIoSocket.java:397)
! at io.socket.engineio.server.EngineIoSocket.lambda$setTransport$10(EngineIoSocket.java:300)
! at io.socket.emitter.Emitter.emit(Emitter.java:123)
! at io.socket.engineio.server.Transport.onPacket(Transport.java:104)
! at io.socket.engineio.server.transport.Polling.lambda$onData$1(Polling.java:197)
! at io.socket.engineio.parser.ParserV4.decodePayload(ParserV4.java:95)
! at io.socket.engineio.server.transport.Polling.onData(Polling.java:192)
! at io.socket.engineio.server.transport.Polling.onDataRequest(Polling.java:282)
! at io.socket.engineio.server.transport.Polling.onRequest(Polling.java:99)
! at io.socket.engineio.server.EngineIoSocket.onRequest(EngineIoSocket.java:213)
! at io.socket.engineio.server.EngineIoServer.handleRequest(EngineIoServer.java:168)
! at app.servlets.SocketIoServlet.service(SocketIoServlet.java:37)

Seems that using inputStream.read() in io.socket.engineio.server.transport.Polling.onDataRequest to stringify a large request body malforms the string.

Replacing

//noinspection ResultOfMethodCallIgnored
inputStream.read(mReadBuffer, 0, mReadBuffer.length);

with

inputStream.readLine(mReadBuffer, 0, mReadBuffer.length);

produced a valid string.

Alternatively, using a BufferedReader with request.getReader() seemed to work too.

StringBuilder buffer = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
    buffer.append(line);
    buffer.append(System.lineSeparator());
}
String data = buffer.toString()

Event problems with JS-client and `[email protected]`

The bug

When I use the JS-[email protected] with a Jetty Server and io.socket/[email protected], I can observe strange behaviour. The client does not receive the events correctly...

It establishes the connection and also sends data:
network_trafic

I have to do some weird workarounds to make the connection work:

// JavaScript
socket.io.on('open', () => {
  socket.onconnect();
});

socket.onAny((data) => {
  console.log('Here comes my data', data);
});

socket.on('message', (msg) => {
  console.log('Here comes no data', data);
});

👀 Ref: socketio/socket.io-client#1597

incompatibility between js and java libraries

Hi,

I'm using the js library socket.io-client v 4.0.2 on the frontend. In the backend I have jetty + socket.io java libs listed below:

compile 'io.socket:socket.io-server:3.0.1'
compile 'io.socket:engine.io-server:4.0.3'
compile 'io.socket:engine.io-server-jetty:4.0.3'

My problem is that my socket reconnect to the server every five second.
It looks like the connection is established because the 'on connect' handler is fired, but it fires every five seconds.
In addition in the chrome webtools I can see the websocket GET request fire every five seconds (on the server side I have async enabled for my servlet).
I supposue this problem is caused by the incompatibility between js and java libraries.
I have experienced very similar issue few months ago when upgraded to v3.
Please let me know which versions of the libs I should use.

Version compatibilities

I couldn't find a confirmed version compatibility table but is 5.x version compatible with 1.x server and client libraries for Socket io v2.x? Or, its better to stay with 1.x of engine.io? Basically following configuration -

        <socket.io-client.version>1.0.1</socket.io-client.version>
        <socket.io-server.version>1.0.3</socket.io-server.version>
        <engine.io-server.version>5.0.0</engine.io-server.version>
        <jetty-server.version>9.4.19.v20190610</jetty-server.version>

I am looking for two features from latest - adding handshake interceptor and setting executor service for server.
TIA!

How to enable permessage-deflate compression on the sever side

I have a website that uses EnginIO on both JS client and Java server. Permessage-deflate compression is enabled by default on the client but to get the compression working I need to I want to enable it on the server-side as well. I have been looking into documentation but I could not find any instruction on how to negotiate with the java server which uses EnginIO to enable permessage-deflate extension Any help is greatly appreciated.

A bug in engineio.parser.ParserV4

`public void encodePayload(List<Packet> packets, boolean supportsBinary, EncodeCallback callback) { final String[] encodedPackets = new String[packets.size()]; for (int i = 0; i < encodedPackets.length; i++) { final Packet packet = packets.get(i);

        final int packetIdx = i;
        encodePacket(packet, false, data -> encodedPackets[packetIdx] = (String) data);
    }

    callback.call(String.join(SEPARATOR, encodedPackets));
}`

it should be :
`public void encodePayload(List<Packet> packets, boolean supportsBinary, EncodeCallback callback) { final String[] encodedPackets = new String[packets.size()]; for (int i = 0; i < encodedPackets.length; i++) { final Packet packet = packets.get(i);

        final int packetIdx = i;
        encodePacket(packet, supportsBinary, data -> encodedPackets[packetIdx] = (String) data);
    }

    callback.call(String.join(SEPARATOR, encodedPackets));
}`

i fould the code during I runing the unit test in your project.

Make it easy to use with Jackson

Right now the library has a hard dependency on org.json. This is problematic for two reasons:

  1. org.json has a non standard license which makes people wary
  2. You many times want your message to be deserialized to a bean type. Creating a JSONObject out of the received JSON is purely overhead.

I haven't looked very deeply into this yet but this code I have in my project does not seem very optimal:

            socket.on("message", ee -> {
                JSONObject json = (JSONObject) ee[0];
                AbstractServerMessage message = objectMapper.readValue(json.toString(), AbstractServerMessage.class);

Cannot invoke "javax.servlet.http.HttpServletRequest.getAttribute(String)" because "this.mPollRequest" is null

I am trying out socket.io to see if it fits our needs and ran into this issue when calling send from multiple threads on the server with long polling enabled. Based on #19 it seems like send should be thread safe but I still occasionally get

    java.lang.NullPointerException: Cannot invoke "javax.servlet.http.HttpServletRequest.getAttribute(String)" because "this.mPollRequest" is null
            at io.socket.engineio.server.transport.Polling.send(Polling.java:118)
            at io.socket.engineio.server.EngineIoSocket.flush(EngineIoSocket.java:422)
            at io.socket.engineio.server.EngineIoSocket.sendPacket(EngineIoSocket.java:413)
            at io.socket.engineio.server.EngineIoSocket.send(EngineIoSocket.java:114)
            at io.socket.socketio.server.SocketIoClient.lambda$sendPacket$0(SocketIoClient.java:74)
            at io.socket.socketio.server.parser.IOParser$Encoder.encode(IOParser.java:39)
            at io.socket.socketio.server.SocketIoClient.sendPacket(SocketIoClient.java:68)
            at io.socket.socketio.server.SocketIoSocket.sendPacket(SocketIoSocket.java:382)
            at io.socket.socketio.server.SocketIoSocket.send(SocketIoSocket.java:218)
            at io.socket.socketio.server.SocketIoSocket.send(SocketIoSocket.java:195)
            at dev.hilla.push.SocketIoServlet.send(SocketIoServlet.java:147)

with io.socket:socket.io-server:jar:4.0.0

Change license to Apache2

This is a issue created for all current contributors to provide their permission to change the license of the repository from MIT to Apache2.

Please state if you're okay or not with changing the license to Apache2.

@Artur-
@YunLemon
@cat9
@afkelsall
@koush

getInitialHeaders and getInitialQuery returns null

When an EngineIoSocket gets created from a web request, The socket gets initialize before the transport runs onRequest. Which means the mInitialQuery and mInitialHeaders are null are they get pulled from the transport which doesn't have those values yet

final EngineIoSocket socket = new EngineIoSocket(lockObject, sid, this, mScheduledExecutor);
final Transport transport = new Polling(lockObject);
socket.init(transport, request);
transport.onRequest(request, response);

Intermittent NullPointerException during upgrade for polling to websocket

Occasionally getting this NPE during the upgrade from polling to websockt, it looks like it happens if the upgrade is happening just after a poll request has been done and before the next one comes in to set the mPollRequest.

Dont have a reproducible testcase for this.

This with version 1.3.5.

java.lang.NullPointerException: null
at io.socket.engineio.server.transport.Polling.send(Polling.java:82) ~[engine.io-server-1.3.5.jar:?]
at io.socket.engineio.server.EngineIoSocket.lambda$upgrade$4(EngineIoSocket.java:174) ~[engine.io-server-1.3.5.jar:?]
at io.socket.emitter.Emitter.emit(Emitter.java:117) ~[engine.io-client-1.0.0.jar:?]
at io.socket.engineio.server.Transport.onPacket(Transport.java:87) ~[engine.io-server-1.3.5.jar:?]
at io.socket.engineio.server.Transport.onData(Transport.java:96) ~[engine.io-server-1.3.5.jar:?]
at io.socket.engineio.server.transport.WebSocket.lambda$new$0(WebSocket.java:25) ~[engine.io-server-1.3.5.jar:?]
at io.socket.emitter.Emitter.emit(Emitter.java:117) ~[engine.io-client-1.0.0.jar:?]
at com.bcdfx.web.ws.EngineIoEndpoint$1.onMessage(EngineIoEndpoint.java:67) ~[classes/:4.8.0]
at com.bcdfx.web.ws.EngineIoEndpoint$1.onMessage(EngineIoEndpoint.java:63) ~[classes/:4.8.0]
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:394) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-websocket.jar:8.5.49]
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-websocket.jar:8.5.49]
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-coyote.jar:8.5.49]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59) [tomcat-coyote.jar:8.5.49]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1783) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.AbstractEndpoint.processSocket(AbstractEndpoint.java:1082) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$2.completed(Nio2Endpoint.java:569) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$2.completed(Nio2Endpoint.java:547) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:969) [tomcat-coyote.jar:8.5.49]
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:898) [tomcat-coyote.jar:8.5.49]
at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127) [?:?]
at sun.nio.ch.Invoker$2.run(Invoker.java:219) [?:?]
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) [?:?]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.5.49]
at java.lang.Thread.run(Thread.java:832) [?:?]

"close" event is not sent on Socket, if it is attached before the Socket upgrade

See here:
https://github.com/socketio/engine.io-server-java/blob/master/engine.io-server/src/main/java/io/socket/engineio/server/EngineIoSocket.java#L135

When the transport upgrades from XHR to WebSocket, all existing close events get cleared out. I am not sure if this is intended behavior, and I am currently working around it by reattaching close events upon receiving an upgrade event.

Repro

  1. wait for "connection" event for EngineIOSocket.
  2. Attach "close" event immediately on EngineIOSocket
  3. Wait for EngineIOSocket client transport to upgrade. Should happen more or less immediately if websocket transport is configured.
  4. Close browser or java engine io client
  5. Observe that the "close" originally attached close event is not fired. It is not even in the internal callback list, because it was cleared during upgrade.

How to reject a client connection?

Hi,
how to reject a client connection properly? I have something like this:

SocketIoNamespace ns = mSocketIoServer.namespace("/");
    ns.on("connection", args -> {
        SocketIoSocket socket = (SocketIoSocket) args[0];
        //verify JWT token
        if (isTokenInvalid()) {
            socket.disconnect(true);
        }
    })

socket.disconnect(true) doesn't interrupt the whole connection process, so I am not sure if it's correct solution (e.g. disconnect() method clears mSockets Map inside SocketIoClient, but right after that, method onConnect() put something to that map and the rest of the connection process takes place).

Thanks for answers.

Java 11 support

Hi. I'm trying to create an engine.io server with Java JDK 11.0.5. Altough I seem to get errors about the AsyncListener class, which was also removed after Java 8. Are there any plans to make it support Java 8+?

Deadlock - Polling Transport

New to github projects, but I think I have found a deadlock in code, that goes back several versions.

The socketTimeout thread is not involved, but I have two threads one writing a message to the session and one servicing a http request.

The thread (PlatMgrDelegate-thread-3) sending the message has gotten the lock on the mWriteBuffer in the EngineIOSocket and is blocked on the send call on the mTransport object which is synchronized.

The thread (https-jsse-nio2-0.0.0.0-2921-exec-131) servicing the http request is inside the PollingTransport owning the lock on it from the synchronized onRequest method, but if fires of a "drain" event that results in the EngineIOSocket.flush being called that attempts to lock the mWriteBuffer which is owned by the PlatMgrDelegate-thread-3 thread.

I was thinking that rather than synchronize on the mWriteBuffer in EngineIOSocket it should probably synchronize on the mTransport in the sendPacket and flush methods, but wanted to get that reviewed by the guys on this project so see if that was a good idea?

Found one Java-level deadlock:

"engineIo-socketTimeout-pool-1":
waiting to lock monitor 0x00007f80e8034b38 (object 0x00000000c2642e68, a io.socket.engineio.server.transport.Polling),
which is held by "https-jsse-nio2-0.0.0.0-2921-exec-131"
"https-jsse-nio2-0.0.0.0-2921-exec-131":
waiting to lock monitor 0x00007f8118041948 (object 0x00000000c2642e48, a java.util.LinkedList),
which is held by "PlatMgrDelegate-thread-3"
"PlatMgrDelegate-thread-3":
waiting to lock monitor 0x00007f80e8034b38 (object 0x00000000c2642e68, a io.socket.engineio.server.transport.Polling),
which is held by "https-jsse-nio2-0.0.0.0-2921-exec-131"

Java stack information for the threads listed above:

"engineIo-socketTimeout-pool-1":
at io.socket.engineio.server.transport.Polling.doClose(Polling.java:138)
- waiting to lock <0x00000000c2642e68> (a io.socket.engineio.server.transport.Polling)
at io.socket.engineio.server.Transport.close(Transport.java:65)
at io.socket.engineio.server.EngineIoSocket.clearTransport(EngineIoSocket.java:228)
at io.socket.engineio.server.EngineIoSocket.onClose(EngineIoSocket.java:261)
at io.socket.engineio.server.EngineIoSocket.lambda$new$0(EngineIoSocket.java:35)
at io.socket.engineio.server.EngineIoSocket$$Lambda$608/303505070.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
"https-jsse-nio2-0.0.0.0-2921-exec-131":
at io.socket.engineio.server.EngineIoSocket.flush(EngineIoSocket.java:307)
- waiting to lock <0x00000000c2642e48> (a java.util.LinkedList)
at io.socket.engineio.server.EngineIoSocket.lambda$setTransport$10(EngineIoSocket.java:209)
at io.socket.engineio.server.EngineIoSocket$$Lambda$612/987190445.call(Unknown Source)
at io.socket.emitter.Emitter.emit(Emitter.java:117)
at io.socket.engineio.server.transport.Polling.onPollRequest(Polling.java:215)
at io.socket.engineio.server.transport.Polling.onRequest(Polling.java:55)
- locked <0x00000000c2642e68> (a io.socket.engineio.server.transport.Polling)
at io.socket.engineio.server.EngineIoSocket.onRequest(EngineIoSocket.java:121)
at io.socket.engineio.server.EngineIoServer.handleRequest(EngineIoServer.java:126)
at com.bcdfx.engineio.nio.EngineIOServlet.service(EngineIOServlet.java:30)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:126)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.filters.CorsFilter.handleNonCORS(CorsFilter.java:364)
at org.apache.catalina.filters.CorsFilter.doFilter(CorsFilter.java:170)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:668)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:615)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1621)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
- locked <0x00000000c5115058> (a org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper)
at org.apache.tomcat.util.net.AbstractEndpoint.processSocket(AbstractEndpoint.java:1082)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$2.completed(Nio2Endpoint.java:566)
at org.apache.tomcat.util.net.Nio2Endpoint$Nio2SocketWrapper$2.completed(Nio2Endpoint.java:544)
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:969)
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:898)
at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
at sun.nio.ch.Invoker$2.run(Invoker.java:218)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
"PlatMgrDelegate-thread-3":
at io.socket.engineio.server.transport.Polling.send(Polling.java:69)
- waiting to lock <0x00000000c2642e68> (a io.socket.engineio.server.transport.Polling)
at io.socket.engineio.server.EngineIoSocket.flush(EngineIoSocket.java:308)
- locked <0x00000000c2642e48> (a java.util.LinkedList)
at io.socket.engineio.server.EngineIoSocket.sendPacket(EngineIoSocket.java:298)
at io.socket.engineio.server.EngineIoSocket.send(EngineIoSocket.java:84)
at com.bcdfx.engineio.nio.DataBridge.onIncomingServerPacket(DataBridge.java:147)
- locked <0x00000000c8152c50> (a com.bcdfx.engineio.nio.DataBridge)
at com.bcdfx.engineio.nio.DataBridge.access$100(DataBridge.java:25)
at com.bcdfx.engineio.nio.DataBridge$2.call(DataBridge.java:52)
at io.socket.emitter.Emitter.emit(Emitter.java:117)
at com.bcdfx.engineio.nio.PlatformManager$MessageRunnable.run(PlatformManager.java:151)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

EngineIO Client could not keep connection alive when using SSL

Hi,

I tried to connect an SSL engine-io server but got failed.

Server Code

The following is my server code, I deploy the servlet in a Jetty Container which is using SSL.

public class SockServlet extends HttpServlet {
    private final EngineIoServer mEngineIoServer = new EngineIoServer();
    private static final Logger logger = Logger.getLogger(ConnectionListener.class.getName());

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        logger.info("Sock Servlet Initialized");

        initIO();
    }

    private void initIO() {
        mEngineIoServer.on("connection", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                EngineIoSocket socket = (EngineIoSocket) args[0];
                logger.info("A client connected: " + socket.getId());
                socket.send(new Packet<>(Packet.MESSAGE, "Hi client, I am here"));

                socket.on("message", new Emitter.Listener() {
                    @Override
                    public void call(Object... objects) {
                        String message = (String) objects[0];
                        logger.info("received: " + message);
                        logger.info("received");
                    }
                });
            }
        });
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        mEngineIoServer.handleRequest(req, resp);
    }

    public EngineIoServer getmEngineIoServer() {
         return mEngineIoServer;
    }
}

maven dependency

<dependency>
        <groupId>io.socket</groupId>
        <artifactId>engine.io-server</artifactId>
        <version>1.3.1</version>
</dependency>

Client Code

I created an engine-io client using engine.io-client.

const io = require('engine.io-client');

const opts = {
  path: '/rest-api/sock',
  rejectUnauthorized: false,
};

const socket = io('https://localhost:8443', opts);
socket.on('open', () => {
  console.log('connected');
})
socket.on('message', (data) => {
  console.log('received: ', data);
});

socket.on('error', (err) => {
  console.log('error', err);
})

console.log('client started');

dependency

 "engine.io-client": "^3.2.1",

Errors

When I executed the client code using node client.js, it showed the first connection has been established, but the connection couldn't keep alive.

client started
connected
received:  Hi client, I am here
error { Error: xhr poll error
    at XHR.Transport.onError (C:\Projects\history-notification-client\node_modules\engine.io-client\lib\transport.js:67:13)
    at Request.<anonymous> (C:\Projects\history-notification-client\node_modules\engine.io-client\lib\transports\polling-xhr.js:130:10)
    at Request.Emitter.emit (C:\Projects\history-notification-client\node_modules\component-emitter\index.js:133:20)
    at Request.onError (C:\Projects\history-notification-client\node_modules\engine.io-client\lib\transports\polling-xhr.js:311:8)
    at Timeout._onTimeout (C:\Projects\history-notification-client\node_modules\engine.io-client\lib\transports\polling-xhr.js:258:18)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5) type: 'TransportError', description: 503 }

Is EngineIoServer / EngineIoSocket thread-safe?

The documentation (site / JavaDoc) does not state anywhere whether EngineIoServer or EngineIoSocket is thread-safe? Can for example socket.send be called from any thread, or does it need to be synchronized by the user?

Is it support to distrubuted

Hello, I want to create socket communication using with distributed system. I found this netty-socketio project bu it's not active in development. does this project support distrubuted structure or will it?

Continuous Connection request to server from engine.io-client

Server: Wildfly 10.1
Browser: Chrome
Frontend: Reactjs
Socket server: engine.io-server-java V 1.3.4
Socket client: engine.io-client V 3.4.0

Note: Followed the below documentation link to host the generic java engine.io server.
https://socketio.github.io/engine.io-server-java/using.html

Issue: When the UI is launched, engine.io triggers the connection request to the sever. When checking the sever log connection request is reached the servlet, now the issue is client is continuously sending the connection request to servlet and WebSocket connection is not establishing it goes like a never-ending process. Attacthed the source for the reference please check and advice want went wrong in the code.

image

Project Structure:

image

ReactJS as front-end:

App.JS

import React from 'react';
var enginesocket = require('engine.io-client')('ws://localhost:8080', { transport: ["websocket"], 
 upgrade: true, reconnection: false });

class App extends React.Component {

 componentDidMount() {
    
    enginesocket.on('open', function () {
      console.log("Opened");
      enginesocket.on('message', function (data) {
        console.log("Message from server :: ", data);
      });
    });
  }
}

EngineIoServlet -

URLPattens is kept as "/" since WAR file name is "engine.io". So the context "/engine.io/" will be exposed by wildfly server.

@WebServlet(name = "EngineIoServlet", urlPatterns = {"/"})
public class EngineIoServlet extends HttpServlet {

    private final EngineIoServer mEngineIoServer = new EngineIoServer();
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("mEngineIoServer?? " + mEngineIoServer);        
        mEngineIoServer.handleRequest(request, response);
        mEngineIoServer.on("connection", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                EngineIoSocket socket = (EngineIoSocket) args[0];
                // Do something with socket like store it somewhere
                System.out.println("socket :: " + socket);
                socket.on("packet", new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Packet packet = (Packet) args[0];
                        // Do something with packet.
                        System.out.println("packet :: " + packet.data);
                    }
                });            
                socket.on("message", new Emitter.Listener() {
                    @Override
                    public void call(Object... args) {
                        Object message = args[0];
                        // message can be either String or byte[]
                        // Do something with message.
                        System.out.println("message ::" + message);
                    }
                });
                socket.send(new Packet<>(Packet.MESSAGE, "foo"));
            }
        });

    }

ApplicationServerConfig


public final class ApplicationServerConfig implements ServerApplicationConfig {

    @Override
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {
        final HashSet<ServerEndpointConfig> result = new HashSet<>();
        result.add(ServerEndpointConfig.Builder
                .create(EngineIoEndpoint.class, "/")
                .build());

        return result;
    }

    @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
        return null;
    }
}

EngineIoEndpoint

public final class EngineIoEndpoint extends Endpoint {

    private Session mSession;
    private Map<String, String> mQuery;
    private EngineIoWebSocket mEngineIoWebSocket;

    private EngineIoServer mEngineIoServer; // The engine.io server instance

    @Override
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        mSession = session;
        mQuery = ParseQS.decode(session.getQueryString());

        System.out.println("inside socket onOpen");

        mEngineIoWebSocket = new EngineIoWebSocketImpl();

        /*
         * These cannot be converted to lambda because of runtime type inference
         * by server.
         */
        mSession.addMessageHandler(new MessageHandler.Whole<String>() {
            @Override
            public void onMessage(String message) {
                mEngineIoWebSocket.emit("message", message);
            }
        });
        mSession.addMessageHandler(new MessageHandler.Whole<byte[]>() {
            @Override
            public void onMessage(byte[] message) {
                mEngineIoWebSocket.emit("message", (Object) message);
            }
        });

        mEngineIoServer.handleWebSocket(mEngineIoWebSocket);
    }

    @Override
    public void onClose(Session session, CloseReason closeReason) {
        super.onClose(session, closeReason);

        mEngineIoWebSocket.emit("close");
        mSession = null;
    }

    @Override
    public void onError(Session session, Throwable thr) {
        super.onError(session, thr);

        mEngineIoWebSocket.emit("error", "unknown error", thr.getMessage());
    }

    private class EngineIoWebSocketImpl extends EngineIoWebSocket {

        private RemoteEndpoint.Basic mBasic;

        EngineIoWebSocketImpl() {
            mBasic = mSession.getBasicRemote();
        }

        @Override
        public Map<String, String> getQuery() {
            return mQuery;
        }

        @Override
        public void write(String message) throws IOException {
            mBasic.sendText(message);
        }

        @Override
        public void write(byte[] message) throws IOException {
            mBasic.sendBinary(ByteBuffer.wrap(message));
        }

        @Override
        public void close() {
            try {
                mSession.close();
            } catch (IOException ignore) {
            }
        }
    }
}

two questions about use socket.io-server-java

hi, i want add websocket support in sprint boot for socket.io js client. i have two questions:

  1. why there is a 40invalid namespace error in download(to client) frames
  2. why my javascript not catch the message recevie event

first , my websocket frames is like this:
image

the conenction is built but server send two packet 40/40Invalid namespace, why?

then, my html is very simple, like this:

<!DOCTYPE HTML>
<html>
<head>
    <title>My WebSocket</title>
</head>

<body>
Welcome<br/>
<input id="text" type="text" /><button onclick="send()">Send</button>    <button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.0/socket.io.js"></script>
<script>
	window.localStorage.debug="*"
	var socket = io('http://localhost:7070',{
		path: '/websocket',
		transports: ['websocket'],
		reconnection: false,
		query:{
			
		}
		
	});
	socket.on('connect', function(){
		console.log('connected')
		setMessageInnerHTML("open");
	});
	socket.on('event', function(data){
		setMessageInnerHTML(data);
	});
	socket.on('disconnect', function(){
		setMessageInnerHTML("close");
	});
	
	socket.on('error', function(error){
		 console.log('error')
		setMessageInnerHTML("error");
	});
	
	socket.on('connect_error', function(error){
		 console.log(error)
		setMessageInnerHTML("connect_error");
	});
	
	function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    function send(){
        var message = document.getElementById('text').value;
        socket.emit("hello",{
			msg:message
		},function(data) {
			console.log(data); 
			setMessageInnerHTML(data);
		});
		console.log('send the data' + message)
    }
</script>
</html>

however ,i can not found any output when i send 'hello' event, i know this code is executed in java when i send hello event:

finally, i give it js debug log and java codes:

socket.io-client:url parse http://localhost:7070 +0ms
browser.js:123 socket.io-client new io instance for http://localhost:7070 +8ms
browser.js:123 socket.io-client:manager readyState closed +1ms
browser.js:123 socket.io-client:manager opening http://localhost:7070 +0ms
browser.js:123 engine.io-client:socket creating transport "websocket" +1ms
browser.js:123 engine.io-client:socket setting transport websocket +2ms
browser.js:123 socket.io-client:manager connect attempt will timeout after 20000 +2ms
browser.js:123 socket.io-client:manager readyState opening +1ms
browser.js:123 engine.io-client:socket socket receive: type "open", data "{"pingInterval":25000,"pingTimeout":5000,"upgrades":["websocket"],"sid":"MWeCPL5"}" +29ms
browser.js:123 engine.io-client:socket socket open +2ms
browser.js:123 socket.io-client:manager open +0ms
browser.js:123 socket.io-client:manager cleanup +1ms
browser.js:123 socket.io-client:socket transport is open - connecting +2ms
browser.js:123 engine.io-client:socket socket receive: type "message", data "0" +4ms
browser.js:123 socket.io-parser decoded 0 as {"type":0,"nsp":"/"} +2ms
socketio.html:29 connected
browser.js:123 engine.io-client:socket socket receive: type "message", data "4Invalid namespace" +2ms
browser.js:123 socket.io-parser decoded 4Invalid namespace as {"type":4,"data":"parser error"} +1ms
browser.js:123 socket.io-client:socket emitting packet with ack id 0 +15s
browser.js:123 socket.io-client:manager writing packet {"type":2,"data":["hello",{"msg":"abc"}],"options":{"compress":true},"id":0,"nsp":"/"} +1ms
browser.js:123 socket.io-parser encoding packet {"type":2,"data":["hello",{"msg":"abc"}],"options":{"compress":true},"id":0,"nsp":"/"} +0ms
browser.js:123 socket.io-parser encoded {"type":2,"data":["hello",{"msg":"abc"}],"options":{"compress":true},"id":0,"nsp":"/"} as 20["hello",{"msg":"abc"}] +1ms
browser.js:123 engine.io-client:socket flushing 1 packets in socket +1ms
socketio.html:63 send the dataabc
browser.js:123 engine.io-client:socket socket receive: type "ping", data "0["hello",{"msg":"abc"}]" +9ms
browser.js:123 engine.io-client:socket writing ping packet - expecting pong within 5000ms +10s
browser.js:123 engine.io-client:socket flushing 1 packets in socket +2ms
browser.js:123 engine.io-client:socket socket receive: type "pong", data "undefined" +4ms
browser.js:123 engine.io-client:socket writing ping packet - expecting pong within 5000ms +26s
browser.js:123 engine.io-client:socket flushing 1 packets in socket +5ms

java code:

       @Bean
	public EngineIoServer socketServer() {
		EngineIoServer engineServer=new EngineIoServer();
		
		engineServer.on("connection", new Emitter.Listener() {
			@Override
			public void call(Object... args) {
				EngineIoSocket socket = (EngineIoSocket) args[0];
				addSocket(socket);
				logger.info("success connection {}",socket.getId());
			}
		});
		
		new SocketIoServer(engineServer);
		return engineServer;
	}

	protected void addSocket(EngineIoSocket socket) {
		socket.on("message", new Emitter.Listener() {
		    @Override
		    public void call(Object... args) {
		       Object message = args[0];
		       logger.info("success receive message... {}",message);
		       socket.send(Parser.decodePacket((String)args[0]));
		    }
		});
		cache.putIfAbsent(UUIDUtils.uuid16(),socket);
	}

i integrate socket.io-server-java to tomcat Endpoint:


@ServerEndpoint(value = "/websocket/")
@Component
public class StandardWebSocketEndpoint extends Endpoint {
   @Override
	public void onOpen(Session session, EndpointConfig config) {
        WebSocketConnectionMeta webSocketMeta=new WebSocketConnectionMeta(session.getRequestParameterMap());
        webSocketMeta.validate();
        boolean checkAuth=doAuthCheck(webSocketMeta);
        if(checkAuth==false)
        {
        	throw new RuntimeException("error when auth for websocket");
        }
        webSocketSessions.putIfAbsent(session,webSocketMeta);
        
        WebSocketAdapter adapter=WebsocketAdapterManager.getAdapter(webSocketMeta);
        adapter.onOpen(webSocketMeta,session);
       
	}

   ...
}

// the adapter method of onOpen:
@Autowired
	private EngineIoServer socketIoServer=null;
	@Override
	public void onOpen(WebSocketConnectionMeta webSocketMeta, Session session) {

		EngineIoWebSocket mEngineIoWebSocket = new EngineIoWebSocketImpl(session);

		session.addMessageHandler(new MessageHandler.Whole<String>() {
			@Override
			public void onMessage(String message) {
				mEngineIoWebSocket.emit("message", message);
			}
		});
		session.addMessageHandler(new MessageHandler.Whole<byte[]>() {
			@Override
			public void onMessage(byte[] message) {
				mEngineIoWebSocket.emit("message", (Object) message);
			}
		});

		socketIoServer.handleWebSocket(mEngineIoWebSocket);

	}

and, the pom.xml:

...
		<dependency>
			<groupId>io.socket</groupId>
			<artifactId>socket.io-server</artifactId>
			<version>1.0.0-SNAPSHOT</version>
		</dependency>
...

Spring Boot Integration

The sample for the Spring Boot integration works fine.

However there is an issue with the WebSocket Handler class, in particular the way the http handler method is defined.

@RequestMapping(
                value = "/engine.io/",
                method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS},
                headers = "Connection!=Upgrade")
        public void httpHandler(HttpServletRequest request, HttpServletResponse response) throws IOException {
            mEngineIoServer.handleRequest(request, response);
        }

One must ensure that this Handler is only called when the client is not requesting a protocol upgrade. However the comparison in the headers evaluation is case sensitive. Some reverse proxies and loadbalancers like AWS Application Loadbalancer tend to correct the actual content of the Connection header and supply it as lowercase. In this case, in order to be able to run both

        @RequestMapping(
                value = "/engine.io/",
                method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS},
                headers = {"connection!=Upgrade", "connection!=upgrade"})

Moving to Java 8+

@darrachequesne I've tried to compile the library on Java 9+ and I've run into issues with uses of DatatypeConverter class. I originally used it because I set the min java version to 7. Dropping support for java 7 will allow me to use Base64 class.
What are your views on dropping java 7 support?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.