这个bug让我头疼一周,忍不住提了issue,你们能改写一下吗?

2026-04-18 01:261阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1492个文字,预计阅读时间需要6分钟。

这个bug让我头疼一周,忍不住提了issue,你们能改写一下吗?

Socket.IO 是一个基于 Node.js 的库,用于实现浏览器和服务器之间的实时双向通信。它支持 WebSockets、轮询和 HTTP 长轮询,适用于多种实时应用场景。

Socket.IO 的应用场景包括:- 在线聊天室- 游戏实时交互- 实时数据监控- 客户端与服务器的同步更新

选择 Socket.IO-client-java 的原因:- 它是官方的 Java 客户端库,支持最新的 Socket.IO 版本。- 便于在 Java 应用中集成实时通信功能。

实战案例:- 在线多人游戏,玩家之间的实时互动。- 实时股票交易系统,用户实时查看股票信息。

参考:- 《socket.io客户端向webserver发送消息实践》- 智客工场

感谢您的阅读,预计阅读时间约2分钟。

这个bug让我头疼一周,忍不住提了issue,你们能改写一下吗?

导航
  • Socket.IO是什么
  • Socket.IO的应用场景
  • 为什么选socket.io-client-java
  • 实战案例
  • 参考

本文首发于智客工坊-《socket.io客户端向webserver发送消息实践》,感谢您的阅读,预计阅读时长2min。

Socket.IO是什么

Socket.IO是一个库,它支持客户端和服务器之间的低延迟双向基于事件的通信。

它构建在WebSocket协议之上,并提供额外的保证,如回退到HTTP长轮询或自动重新连接。



Socket.IO的应用场景

Socket.IO目前应用比较多的场景就是网页的IM实时聊天。

Notes: 在C#中,也有个类库signalr实现简单的网页实时聊天。

Socket.IO server端有以下几种不同编程语言的实现:

  • JavaScript (whose documentation can be found here on this website)
    • Installation steps
    • API
    • Source code
  • Java: github.com/mrniko/netty-socketio
  • Java: github.com/trinopoty/socket.io-server-java
  • Python: github.com/miguelgrinberg/python-socketio
  • Golang: github.com/googollee/go-socket.io

Socket.IO client端,大多数主流编程语言的也有实现

  • JavaScript (which can be run either in the browser, in Node.js or in React Native)
    • Installation steps
    • API
    • Source code
  • Java: github.com/socketio/socket.io-client-java
  • C++: github.com/socketio/socket.io-client-cpp
  • Swift: github.com/socketio/socket.io-client-swift
  • Dart: github.com/rikulo/socket.io-client-dart
  • Python: github.com/miguelgrinberg/python-socketio
  • .Net: github.com/doghappy/socket.io-client-csharp
  • Rust: github.com/1c3t3a/rust-socketio
  • Kotlin: github.com/icerockdev/moko-socket-io
为什么选socket.io-client-java

本文主要是针对socket.io-client-java的一次实践。

我们团队已经使用Node.js搭建了webserver,并实现了web客户端和webserver的消息互通(即双方都是基于JavaScript的实现)。

但是,有个特殊业务场景,需要在我们后端业务接口中根据业务状态变更向指定的IM会话投递实时消息。

这种需求的实现方案:

  • 方案1,后端业务接口将消息投递到kafka topic,再由webserver消费指定topic,实现消息的实时推送
  • 方案2,后端直接连接webserver,然后投递消息

综合考虑之后,我们选择了方案2。

因此,技术选型上就只有华山一条路——socket.io-client-java

在实现的过程中,也确实是踩了一些坑,所以记录一下,顺便和大家分享一下。

实战案例

现在我们开始socket.io-client-java
之旅吧!

引入socket.io-client-java

Notice: socket.io客户端和服务端的版本要匹配,否则会连不上或者没有反应。

根据socket.io-client-java官方文档给出的版本匹配表格:

Client version Socket.IO server 0.9.x 1.x 1.x 2.x 2.x 3.x / 4.x

因为我们webserver端的socket.io 版本 "socket.io": "^2.4.1"

所以,客户端我只能选择1.x,这里选择1.0.0。

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

maven更新之后,即可使用。



代码实现

package com.zhike.blogmanager.Msg; import io.socket.client.IO; import io.socket.client.Socket; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j; import org.apache.poi.ddf.EscherColorRef; import org.json.JSONException; import org.json.JSONObject; import org.springframework.stereotype.Component; import java.net.URI; import java.util.Date; /** * Created with IntelliJ IDEA. * User: lenovo * Date: 2022/6/25 * Time: 21:25 * Description: No Description */ @Component @RequiredArgsConstructor public class PushMessageManager { private Socket socket; /** * 消息推送到webserver * */ public void pushToWebServer() { //保证只会实例化一次socket if(socket==null) { connentSocket(); System.out.println(socket); } //构造JSONObject对象 JSONObject data=bulidMsg(); System.out.println(""+data); //event 要和webserver一致才能接受到消息 socket.emit("2",data); if(!socket.connected()) { socket.connect(); } } private void connentSocket(){ try { //String url ="172.xx.xx.xx:3000"; //String url ="172.xx.xx.xx:3001"; String url = "172.xx.xx.xx:3002";//web服务器地址以实际为准 IO.Options options = new IO.Options(); options.forceNew = true; // 失败重连时间间隔 options.reconnectionDelay = 1000; // 连接超时时间 options.timeout = 5000; socket = IO.socket(URI.create(url), options); }catch (Exception ex) { System.out.println("连接服务器失败,error:"+ex); } } /** * 消息体构造 * 定义须和webserver保持一致,webserver才能解析 * */ private JSONObject bulidMsg() { JSONObject data = new JSONObject(); try { data.put("type", "1"); data.put("from", "[FromUSerId]"); data.put("to", "[ToUserId]"); data.put("msgContent", "Hello World!"); data.put("msgTime", new Date()); } catch (JSONException e) { throw new AssertionError(e); } return data; } }

代码中有详细注释,不再赘述。

断线重连的坑

这里还有个巨坑,不知道是否是socket.io-client-java的bug。

如果webserver部署了多个应用并被nginx负载,如下:

server { listen 3000; server_name localhost; access_log /data/logs/nginx/webserver/access.log main; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass webserver-nodes; # enable WebSockets proxy_172.xx.xx.xx:3000"的时候,就会出现socket会在两台webserver之间disconnect,reconnect的情况。

当时同事反馈,使用JavaScript client连接是正常的。

这个研究了两三天了,尝试了很多方式依然没有解决。

所以,最终我们只能指定连接其中一台webserver。

最后

最后给提了一个issue #715



参考
  • socket.io/docs/v4/
  • huongdanjava.com/websocket-with-socket-io-java.html
  • github.com/socketio/socket.io-client-java
  • socketio.github.io/socket.io-client-java/emitting_events.html

本文共计1492个文字,预计阅读时间需要6分钟。

这个bug让我头疼一周,忍不住提了issue,你们能改写一下吗?

Socket.IO 是一个基于 Node.js 的库,用于实现浏览器和服务器之间的实时双向通信。它支持 WebSockets、轮询和 HTTP 长轮询,适用于多种实时应用场景。

Socket.IO 的应用场景包括:- 在线聊天室- 游戏实时交互- 实时数据监控- 客户端与服务器的同步更新

选择 Socket.IO-client-java 的原因:- 它是官方的 Java 客户端库,支持最新的 Socket.IO 版本。- 便于在 Java 应用中集成实时通信功能。

实战案例:- 在线多人游戏,玩家之间的实时互动。- 实时股票交易系统,用户实时查看股票信息。

参考:- 《socket.io客户端向webserver发送消息实践》- 智客工场

感谢您的阅读,预计阅读时间约2分钟。

这个bug让我头疼一周,忍不住提了issue,你们能改写一下吗?

导航
  • Socket.IO是什么
  • Socket.IO的应用场景
  • 为什么选socket.io-client-java
  • 实战案例
  • 参考

本文首发于智客工坊-《socket.io客户端向webserver发送消息实践》,感谢您的阅读,预计阅读时长2min。

Socket.IO是什么

Socket.IO是一个库,它支持客户端和服务器之间的低延迟双向基于事件的通信。

它构建在WebSocket协议之上,并提供额外的保证,如回退到HTTP长轮询或自动重新连接。



Socket.IO的应用场景

Socket.IO目前应用比较多的场景就是网页的IM实时聊天。

Notes: 在C#中,也有个类库signalr实现简单的网页实时聊天。

Socket.IO server端有以下几种不同编程语言的实现:

  • JavaScript (whose documentation can be found here on this website)
    • Installation steps
    • API
    • Source code
  • Java: github.com/mrniko/netty-socketio
  • Java: github.com/trinopoty/socket.io-server-java
  • Python: github.com/miguelgrinberg/python-socketio
  • Golang: github.com/googollee/go-socket.io

Socket.IO client端,大多数主流编程语言的也有实现

  • JavaScript (which can be run either in the browser, in Node.js or in React Native)
    • Installation steps
    • API
    • Source code
  • Java: github.com/socketio/socket.io-client-java
  • C++: github.com/socketio/socket.io-client-cpp
  • Swift: github.com/socketio/socket.io-client-swift
  • Dart: github.com/rikulo/socket.io-client-dart
  • Python: github.com/miguelgrinberg/python-socketio
  • .Net: github.com/doghappy/socket.io-client-csharp
  • Rust: github.com/1c3t3a/rust-socketio
  • Kotlin: github.com/icerockdev/moko-socket-io
为什么选socket.io-client-java

本文主要是针对socket.io-client-java的一次实践。

我们团队已经使用Node.js搭建了webserver,并实现了web客户端和webserver的消息互通(即双方都是基于JavaScript的实现)。

但是,有个特殊业务场景,需要在我们后端业务接口中根据业务状态变更向指定的IM会话投递实时消息。

这种需求的实现方案:

  • 方案1,后端业务接口将消息投递到kafka topic,再由webserver消费指定topic,实现消息的实时推送
  • 方案2,后端直接连接webserver,然后投递消息

综合考虑之后,我们选择了方案2。

因此,技术选型上就只有华山一条路——socket.io-client-java

在实现的过程中,也确实是踩了一些坑,所以记录一下,顺便和大家分享一下。

实战案例

现在我们开始socket.io-client-java
之旅吧!

引入socket.io-client-java

Notice: socket.io客户端和服务端的版本要匹配,否则会连不上或者没有反应。

根据socket.io-client-java官方文档给出的版本匹配表格:

Client version Socket.IO server 0.9.x 1.x 1.x 2.x 2.x 3.x / 4.x

因为我们webserver端的socket.io 版本 "socket.io": "^2.4.1"

所以,客户端我只能选择1.x,这里选择1.0.0。

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

maven更新之后,即可使用。



代码实现

package com.zhike.blogmanager.Msg; import io.socket.client.IO; import io.socket.client.Socket; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j; import org.apache.poi.ddf.EscherColorRef; import org.json.JSONException; import org.json.JSONObject; import org.springframework.stereotype.Component; import java.net.URI; import java.util.Date; /** * Created with IntelliJ IDEA. * User: lenovo * Date: 2022/6/25 * Time: 21:25 * Description: No Description */ @Component @RequiredArgsConstructor public class PushMessageManager { private Socket socket; /** * 消息推送到webserver * */ public void pushToWebServer() { //保证只会实例化一次socket if(socket==null) { connentSocket(); System.out.println(socket); } //构造JSONObject对象 JSONObject data=bulidMsg(); System.out.println(""+data); //event 要和webserver一致才能接受到消息 socket.emit("2",data); if(!socket.connected()) { socket.connect(); } } private void connentSocket(){ try { //String url ="172.xx.xx.xx:3000"; //String url ="172.xx.xx.xx:3001"; String url = "172.xx.xx.xx:3002";//web服务器地址以实际为准 IO.Options options = new IO.Options(); options.forceNew = true; // 失败重连时间间隔 options.reconnectionDelay = 1000; // 连接超时时间 options.timeout = 5000; socket = IO.socket(URI.create(url), options); }catch (Exception ex) { System.out.println("连接服务器失败,error:"+ex); } } /** * 消息体构造 * 定义须和webserver保持一致,webserver才能解析 * */ private JSONObject bulidMsg() { JSONObject data = new JSONObject(); try { data.put("type", "1"); data.put("from", "[FromUSerId]"); data.put("to", "[ToUserId]"); data.put("msgContent", "Hello World!"); data.put("msgTime", new Date()); } catch (JSONException e) { throw new AssertionError(e); } return data; } }

代码中有详细注释,不再赘述。

断线重连的坑

这里还有个巨坑,不知道是否是socket.io-client-java的bug。

如果webserver部署了多个应用并被nginx负载,如下:

server { listen 3000; server_name localhost; access_log /data/logs/nginx/webserver/access.log main; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass webserver-nodes; # enable WebSockets proxy_172.xx.xx.xx:3000"的时候,就会出现socket会在两台webserver之间disconnect,reconnect的情况。

当时同事反馈,使用JavaScript client连接是正常的。

这个研究了两三天了,尝试了很多方式依然没有解决。

所以,最终我们只能指定连接其中一台webserver。

最后

最后给提了一个issue #715



参考
  • socket.io/docs/v4/
  • huongdanjava.com/websocket-with-socket-io-java.html
  • github.com/socketio/socket.io-client-java
  • socketio.github.io/socket.io-client-java/emitting_events.html