Java Websocket实例 不念不忘少年蓝@ 2022-06-09 07:28 181阅读 0赞 记录下自己在用的websocket 介绍 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏览器需要不断的向服务器发出请求,然而HTTP request 的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽。 而最比较新的技术去做轮询的效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。 在 WebSocket API,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。 ### 运行环境: ### 实现了websocket的浏览器: <table style="color:rgb(0,0,0); font-size:12px; border-collapse:collapse; border-spacing:0px; margin:5px 0px; line-height:22px; font-family:arial,宋体,sans-serif"> <tbody> <tr> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Chrome </div> </td> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Supported in version 4+ </div> </td> </tr> <tr> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Firefox </div> </td> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Supported in version 4+ </div> </td> </tr> <tr> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Internet Explorer </div> </td> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Supported in version 10+ </div> </td> </tr> <tr> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Opera </div> </td> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Supported in version 10+ </div> </td> </tr> <tr> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Safari </div> </td> <td style="margin:0px; padding:2px 10px; height:22px; border:1px solid rgb(230,230,230)"> <div style="color:rgb(51,51,51); margin:0px; line-height:24px"> Supported in version 5+ </div> </td> </tr> </tbody> </table> 依赖: Tomcat 7 或者 J2EE7 Java代码 ![收藏代码][icon_star.png] 1. <dependency> 2. <groupId>org.apache.tomcat</groupId> 3. <artifactId>tomcat-websocket-api</artifactId> 4. <version>7.0.47</version> 5. <scope>provided</scope> 6. </dependency> 7. 8. 9. <dependency> 10. <groupId>javax</groupId> 11. <artifactId>javaee-api</artifactId> 12. <version>7.0</version> 13. <scope>provided</scope> 14. </dependency> 注意:早前业界没有统一的标准,各服务器都有各自的实现,现在**J2EE7**的**JSR356**已经定义了统一的标准,请尽量使用支持最新通用标准的服务器。 详见:http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html http://jinnianshilongnian.iteye.com/blog/1909962 我是用的Tomcat 7.0.57 + Java7 必须是Tomcat 7.0.47以上 详见:http://www.iteye.com/news/28414 ps:最早我们是用的Tomcat 7自带的实现,后来要升级Tomcat 8,结果原来的实现方式在Tomcat 8不支持了,就只好切换到支持Websocket 1.0版本的Tomcat了。 主流的java web服务器都有支持JSR365标准的版本了,请自行Google。 **用nginx做反向代理的需要注意啦,socket请求需要做特殊配置的,切记!** Tomcat的处理方式建议修改为NIO的方式,同时修改连接数到合适的参数,请自行Google! # 服务端 # 服务端不需要在web.xml中做额外的配置,Tomcat启动后就可以直接连接了。 Java代码 ![收藏代码][icon_star.png] 1. **import** com.dooioo.websocket.utils.SessionUtils; 2. **import** org.apache.commons.logging.Log; 3. **import** org.apache.commons.logging.LogFactory; 4. 5. **import** javax.websocket.\*; 6. **import** javax.websocket.server.PathParam; 7. **import** javax.websocket.server.ServerEndpoint; 8. 9. /\*\* 10. \* 功能说明:websocket处理类, 使用J2EE7的标准 11. \* 切忌直接在该连接处理类中加入业务处理代码 12. \* 作者:liuxing(2014-11-14 04:20) 13. \*/ 14. //relationId和userCode是我的业务标识参数,websocket.ws是连接的路径,可以自行定义 15. @ServerEndpoint("/websocket.ws/\{relationId\}/\{userCode\}") 16. **public** **class** WebsocketEndPoint \{ 17. 18. **private** **static** Log log = LogFactory.getLog(WebsocketEndPoint.**class**); 19. 20. /\*\* 21. \* 打开连接时触发 22. \* @param relationId 23. \* @param userCode 24. \* @param session 25. \*/ 26. @OnOpen 27. **public** **void** onOpen(@PathParam("relationId") String relationId, 28. @PathParam("userCode") **int** userCode, 29. Session session)\{ 30. log.info("Websocket Start Connecting: " + SessionUtils.getKey(relationId, userCode)); 31. SessionUtils.put(relationId, userCode, session); 32. \} 33. 34. /\*\* 35. \* 收到客户端消息时触发 36. \* @param relationId 37. \* @param userCode 38. \* @param message 39. \* @return 40. \*/ 41. @OnMessage 42. **public** String onMessage(@PathParam("relationId") String relationId, 43. @PathParam("userCode") **int** userCode, 44. String message) \{ 45. **return** "Got your message (" + message + ").Thanks !"; 46. \} 47. 48. /\*\* 49. \* 异常时触发 50. \* @param relationId 51. \* @param userCode 52. \* @param session 53. \*/ 54. @OnError 55. **public** **void** onError(@PathParam("relationId") String relationId, 56. @PathParam("userCode") **int** userCode, 57. Throwable throwable, 58. Session session) \{ 59. log.info("Websocket Connection Exception: " + SessionUtils.getKey(relationId, userCode)); 60. log.info(throwable.getMessage(), throwable); 61. SessionUtils.remove(relationId, userCode); 62. \} 63. 64. /\*\* 65. \* 关闭连接时触发 66. \* @param relationId 67. \* @param userCode 68. \* @param session 69. \*/ 70. @OnClose 71. **public** **void** onClose(@PathParam("relationId") String relationId, 72. @PathParam("userCode") **int** userCode, 73. Session session) \{ 74. log.info("Websocket Close Connection: " + SessionUtils.getKey(relationId, userCode)); 75. SessionUtils.remove(relationId, userCode); 76. \} 77. 78. \} 工具类用来存储唯一key和连接 这个是我业务的需要,我的业务是服务器有对应动作触发时,推送数据到客户端,没有接收客户端数据的操作。 Java代码 ![收藏代码][icon_star.png] 1. **import** javax.websocket.Session; 2. **import** java.util.Map; 3. **import** java.util.concurrent.ConcurrentHashMap; 4. 5. /\*\* 6. \* 功能说明:用来存储业务定义的sessionId和连接的对应关系 7. \* 利用业务逻辑中组装的sessionId获取有效连接后进行后续操作 8. \* 作者:liuxing(2014-12-26 02:32) 9. \*/ 10. **public** **class** SessionUtils \{ 11. 12. **public** **static** Map<String, Session> clients = **new** ConcurrentHashMap<>(); 13. 14. **public** **static** **void** put(String relationId, **int** userCode, Session session)\{ 15. clients.put(getKey(relationId, userCode), session); 16. \} 17. 18. **public** **static** Session get(String relationId, **int** userCode)\{ 19. **return** clients.get(getKey(relationId, userCode)); 20. \} 21. 22. **public** **static** **void** remove(String relationId, **int** userCode)\{ 23. clients.remove(getKey(relationId, userCode)); 24. \} 25. 26. /\*\* 27. \* 判断是否有连接 28. \* @param relationId 29. \* @param userCode 30. \* @return 31. \*/ 32. **public** **static** **boolean** hasConnection(String relationId, **int** userCode) \{ 33. **return** clients.containsKey(getKey(relationId, userCode)); 34. \} 35. 36. /\*\* 37. \* 组装唯一识别的key 38. \* @param relationId 39. \* @param userCode 40. \* @return 41. \*/ 42. **public** **static** String getKey(String relationId, **int** userCode) \{ 43. **return** relationId + "\_" + userCode; 44. \} 45. 46. \} 推送数据到客户端 在其他业务方法中调用 Java代码 ![收藏代码][icon_star.png] 1. /\*\* 2. \* 将数据传回客户端 3. \* 异步的方式 4. \* @param relationId 5. \* @param userCode 6. \* @param message 7. \*/ 8. **public** **void** broadcast(String relationId, **int** userCode, String message) \{ 9. **if** (TelSocketSessionUtils.hasConnection(relationId, userCode)) \{ 10. TelSocketSessionUtils.get(relationId, userCode).getAsyncRemote().sendText(message); 11. \} **else** \{ 12. **throw** **new** NullPointerException(TelSocketSessionUtils.getKey(relationId, userCode) + " Connection does not exist"); 13. \} 14. 15. \} 我是使用异步的方法推送数据,还有同步的方法 详见:http://docs.oracle.com/javaee/7/api/javax/websocket/Session.html # 客户端 # Js代码 ![收藏代码][icon_star.png] 1. **var** webSocket = **null**; 2. **var** tryTime = 0; 3. $(**function** () \{ 4. initSocket(); 5. 6. window.onbeforeunload = **function** () \{ 7. //离开页面时的其他操作 8. \}; 9. \}); 10. 11. /\*\* 12. \* 初始化websocket,建立连接 13. \*/ 14. **function** initSocket() \{ 15. **if** (!window.WebSocket) \{ 16. alert("您的浏览器不支持websocket!"); 17. **return** **false**; 18. \} 19. 20. webSocket = **new** WebSocket("ws://127.0.0.1:8080/websocket.ws/" + relationId + "/" + userCode); 21. 22. // 收到服务端消息 23. webSocket.onmessage = **function** (msg) \{ 24. console.log(msg); 25. \}; 26. 27. // 异常 28. webSocket.onerror = **function** (event) \{ 29. console.log(event); 30. \}; 31. 32. // 建立连接 33. webSocket.onopen = **function** (event) \{ 34. console.log(event); 35. \}; 36. 37. // 断线重连 38. webSocket.onclose = **function** () \{ 39. // 重试10次,每次之间间隔10秒 40. **if** (tryTime < 10) \{ 41. setTimeout(**function** () \{ 42. webSocket = **null**; 43. tryTime++; 44. initSocket(); 45. \}, 500); 46. \} **else** \{ 47. tryTime = 0; 48. \} 49. \}; 50. 51. \} 其他调试工具 Java实现一个websocket的客户端 Java代码 ![收藏代码][icon_star.png] 1. <dependency> 2. <groupId>org.java-websocket</groupId> 3. <artifactId>Java-WebSocket</artifactId> 4. <version>1.3.0</version> 5. </dependency> Java代码 ![收藏代码][icon_star.png] 1. **import** java.io.IOException; 2. **import** javax.websocket.ClientEndpoint; 3. **import** javax.websocket.OnError; 4. **import** javax.websocket.OnMessage; 5. **import** javax.websocket.OnOpen; 6. **import** javax.websocket.Session; 7. 8. @ClientEndpoint 9. **public** **class** MyClient \{ 10. @OnOpen 11. **public** **void** onOpen(Session session) \{ 12. System.out.println("Connected to endpoint: " + session.getBasicRemote()); 13. **try** \{ 14. session.getBasicRemote().sendText("Hello"); 15. \} **catch** (IOException ex) \{ 16. \} 17. \} 18. 19. @OnMessage 20. **public** **void** onMessage(String message) \{ 21. System.out.println(message); 22. \} 23. 24. @OnError 25. **public** **void** onError(Throwable t) \{ 26. t.printStackTrace(); 27. \} 28. \} Java代码 ![收藏代码][icon_star.png] 1. **import** java.io.BufferedReader; 2. **import** java.io.IOException; 3. **import** java.io.InputStreamReader; 4. **import** java.net.URI; 5. **import** javax.websocket.ContainerProvider; 6. **import** javax.websocket.DeploymentException; 7. **import** javax.websocket.Session; 8. **import** javax.websocket.WebSocketContainer; 9. 10. **public** **class** MyClientApp \{ 11. 12. **public** Session session; 13. 14. **protected** **void** start() 15. \{ 16. 17. WebSocketContainer container = ContainerProvider.getWebSocketContainer(); 18. 19. String uri = "ws://127.0.0.1:8080/websocket.ws/relationId/12345"; 20. System.out.println("Connecting to " + uri); 21. **try** \{ 22. session = container.connectToServer(MyClient.**class**, URI.create(uri)); 23. \} **catch** (DeploymentException e) \{ 24. e.printStackTrace(); 25. \} **catch** (IOException e) \{ 26. e.printStackTrace(); 27. \} 28. 29. \} 30. **public** **static** **void** main(String args\[\])\{ 31. MyClientApp client = **new** MyClientApp(); 32. client.start(); 33. 34. BufferedReader br = **new** BufferedReader(**new** InputStreamReader(System.in)); 35. String input = ""; 36. **try** \{ 37. **do**\{ 38. input = br.readLine(); 39. **if**(!input.equals("exit")) 40. client.session.getBasicRemote().sendText(input); 41. 42. \}**while**(!input.equals("exit")); 43. 44. \} **catch** (IOException e) \{ 45. // TODO Auto-generated catch block 46. e.printStackTrace(); 47. \} 48. \} 49. \} Chrome安装一个websocket模拟客户端 ![点击查看原始大小图片][2a845c94-b855-3d13-a090-6d690acf3786.png] # 最后 # 为了统一的操作体验,对于一些不支持websocket的浏览器,请使用socketjs技术做客户端开发。 [icon_star.png]: /images/20220609/27ccdd8949e0479294f79494dbd9bb20.png [2a845c94-b855-3d13-a090-6d690acf3786.png]: /images/20220609/69b312fa405c48f19f65e6f0c21c02ae.png
相关 使用Java WebSocket实现双向通信的实例 以下是一个简单的Java WebSocket实现双向通信的例子。这个例子使用了Java Websocket API和Spring Boot框架。 首先,我们需要创建一个Web 电玩女神/ 2024年10月09日 22:24/ 0 赞/ 38 阅读
相关 Spring Boot整合Java WebSocket通信问题实例 在Spring Boot中集成Java WebSocket(通常称为WebSocket)是一个常见的Web开发需求。以下将提供一个简单的例子来展示这个过程的问题和解决方法。 小灰灰/ 2024年09月19日 05:21/ 0 赞/ 65 阅读
相关 使用Java WebSocket进行实时通信的实例 在Java中,WebSocket通常通过javax.websocket.WebSocketServlet来实现。以下是一个简单的WebSocket服务器示例: ```java ╰+攻爆jí腚メ/ 2024年09月15日 09:45/ 0 赞/ 51 阅读
相关 Java WebSocket开发入门实例分析 WebSocket是HTML5中的一种API,用于在单个TCP连接上进行全双工通信。以下是一个简单的Java WebSocket开发入门实例: 1. **依赖引入**: 水深无声/ 2024年09月11日 13:27/ 0 赞/ 33 阅读
相关 HTML5 WebSocket 简单实例 什么是WebSocket WebSocket 简单实例 什么是WebSocket WebSocket是HTML5开始提供的一种在单个 TCP 男娘i/ 2022年07月19日 05:30/ 0 赞/ 190 阅读
相关 Java Websocket实例 记录下自己在用的websocket 介绍 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出 不念不忘少年蓝@/ 2022年06月09日 07:28/ 0 赞/ 182 阅读
相关 WebSocket_实例 握手协议的客户端数据已经由浏览器代劳了,服务器端需要我们自己来实现,目前市场上开源的实现也比较多如: Kaazing WebSocket Gateway(一个 Jav 桃扇骨/ 2022年05月25日 12:19/ 0 赞/ 227 阅读
相关 Java后端WebSocket的Tomcat实例 一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出 约定不等于承诺〃/ 2022年04月18日 00:45/ 0 赞/ 160 阅读
相关 最精简的 Websocket 实例 创建一个 HTML 文件,内容为: <!DOCTYPE html> <html> <header> <script> 深藏阁楼爱情的钟/ 2022年04月08日 15:53/ 0 赞/ 205 阅读
还没有评论,来说两句吧...