I’m working with socketio and netty with java and I’m new to both of them.
my client side code looks like this.
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title >webSocket test</title> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script> < !-- New Bootstrap core CSS file--> <!-- Optional Bootstrap theme file (generally not necessary to import) --> <!- -jQuery file. Be sure to introduce before bootstrap.min.js --> <!-- The latest Bootstrap core JavaScript file--> <script type=" text/javascript"> $(function(){ /** * The socket.emit("event name", "parameter data") method of the front-end js is used when triggering the back-end custom message event, * front-end js The socket.on("event name", anonymous function (data sent by the server to the client)) for monitoring server-side events **/ //io({path: 'ws://localhost:9099/', transports: ['websocket'] ,upgrade: false}); var socket = io.connect("ws://localhost:9099",{transports: ['websocket'] ,upgrade: false}); var firstconnect = true; if(firstconnect) { console.log("First connection initialization"); //Monitor server connection event socket.on('connect',function(){ socket.emit('messageEvent', 'Hello server'); console.log("First connection success"); $("#tou").html("Connect to the server successfully!"); }); //Monitor server shutdown service event socket.on('disconnect', function(){ $("#tou").html("Disconnected from the server!"); }); //Monitor server Send message event socket.on('responseEvent', function(data) { console.log('data'); $("#msg").html($("#msg").html() + "<br/>" + data); } ); firstconnect = false; } else { console.log("why?"); socket.socket.reconnect(); } $('#send').bind('click', function() { send(); }); function send(){ if (socket != null) { var message = document.getElementById('message').value; var title = "message"; var obj = {message:message,title:title}; var str = JSON.stringify(obj); socket.emit("messageEvent",str); console.log("message event" , str); } else { alert('Send'); } } }); </script> </head> <body> <div class="page-header" id="tou"> webSocket Demo </div> <div class="well" id="msg"> </div> <div class="col-lg"> <div class="input-group"> <input type="text" class="form-control" placeholder="send Message..." id="message"> <span class="input-group-btn"> <button class="btn btn-default" type="button" id="send" >send</button> </span> </div><!-- /input-group --> </div><!-- /.col-lg-6 --> </div><!-- /.row --><br><br> </body> </html>
The event handler is as shown below.
@Component public class MessageEventHandler { private static final Logger logger = LoggerFactory.getLogger(MessageEventHandler.class); public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>(); @Autowired private RedissonClient redisson; @Resource private SocketIOServer socketIOServer; @OnConnect public void onConnect(SocketIOClient client){ Map<String,Object> clientMap = new HashMap<>(16); client.sendEvent("responseEvent", client.getSessionId().toString()+": "+ "hello"); if(client!=null){ String room = client.getHandshakeData().getSingleUrlParam("room"); String nameSpace = client.getNamespace().getName(); logger.info("namespace {} ",nameSpace); String sessionId = client.getSessionId().toString(); logger.info("namespace, room={}, sessionId={},namespace={}",room,sessionId,nameSpace); if(StringUtils.isEmpty(room)){ //client.joinRoom(room); clientMap.put("rooms",room); } clientMap.put("createTime", LocalDateTime.now().toString()); redisson.getBucket("room"+sessionId).trySet(clientMap); } return; } /** * Triggered when the client closes the connection * * @param client */ @OnDisconnect public void onDisconnect(SocketIOClient client) { logger.info("client:" + client.getSessionId() + "disconnected"); } /** * Client events * * @param client * @param request * @param msg */ @OnEvent(value = "messageEvent") public void onMessageEvent(SocketIOClient client, AckRequest request, String msg) { System.out.println("haha"); logger.info("message :" + msg); //Post the message back JSONObject jsonObject = JSON.parseObject(msg); String message = jsonObject.getString("message"); Collection<SocketIOClient> clients = socketIOServer.getBroadcastOperations().getClients(); for (SocketIOClient clientByRoom : clients) { clientByRoom.sendEvent("responseEvent", client.getSessionId().toString()+": "+message); } } }
The server starter code is shown below.
@Component @Order(1) public class SocketServerRunner implements CommandLineRunner { private static Logger logger = LoggerFactory.getLogger(SocketServerRunner.class); @Resource private SocketIOServer socketIOServer; @Resource private PubSubStore pubSubStore; @Autowired private RedissonClient redisson; @Override public void run(String... args) throws Exception { logger.info("socketIOServer "); socketIOServer.start(); pubSubStore.subscribe(PubSubType.DISPATCH, data -> { Collection<SocketIOClient> clients = null; String room = data.getRoom(); String namespace = data.getNamespace(); Packet packet = data.getPacket(); String jsonData = packet.getData(); if(!StringUtils.isEmpty(namespace)){ SocketIONamespace socketIONamespace = socketIOServer.getNamespace(namespace); if(StringUtils.isEmpty(room)){ clients = socketIONamespace.getRoomOperations(room).getClients(); } }else{ clients = socketIOServer.getBroadcastOperations().getClients(); } if(!CollectionUtils.isEmpty(clients)){ for (SocketIOClient client : clients) { client.sendEvent("messageEvent",jsonData); } } }, DispatchMessage.class); // addNameSpace(socketIOServer); }
I’m getting a connection registration on the OnConnect
annoted method, but the method seems to run two times cause I get the log twice while the socket connects. I don’t know why it happens.
But even worse is the emit method doesn’t work that is written in client side javascript. There is no error. The log below the emit is executed. But the OnEvent
annoted method in the java EventHandler doesn’t seem to detect it.
Can someone help me understand this?
Advertisement
Answer
Apparently it seems the problem is with the libraries. There is some compatibility issue with newer versions of socketio client library with netty dependencies for java and it is causing the weird problems.
My dependency for netty socketio is shown below which obviously is the latest as of answering this question.
<dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.19</version> </dependency>
And for the client library to work smoothly I had to downgrade the library from 3.X.X to 2.X.X .
In my case from
<script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script>
to
<script src="https://cdn.bootcss.com/socket.io/2.1.1/socket.io.js"></script>