当前位置:   article > 正文

基于netty-socket.io给指定客户端发送消息_config.setauthorizationlistener

config.setauthorizationlistener

前言:

1、使用netty-socketio搭建socketIo服务;

2、client连接socketIo服务时,保存下该client对象;

3、使用TestController,向指定client推送消息;

一、netty-socket.io版本;

  1. <dependency>
  2. <groupId>com.corundumstudio.socketio</groupId>
  3. <artifactId>netty-socketio</artifactId>
  4. <version>1.7.16</version>
  5. </dependency>

二、创建socketIoServer实例;

  1. /**
  2. * 创建socketIOServer实例
  3. * @return
  4. */
  5. @Bean
  6. public SocketIOServer socketIOServer() {
  7. com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
  8. config.setHostname(host);
  9. config.setPort(port);
  10. setAuthorizationListener(config);
  11. return new SocketIOServer(config);
  12. }

三、socketIo client连接校验说明;

设想是通过服务端颁发token给client页面,当client页面进行连接时,将服务端颁发的token传递回来。服务端通过client传递的一系列参数,取出服务端保存的token,与传递的token做验证。

本文未做上述逻辑校验,仅是将client传递的参数打印在控制台。

  1. /**
  2. * 设置socketio client连接时的安全校验
  3. * @param config
  4. */
  5. private void setAuthorizationListener(com.corundumstudio.socketio.Configuration config) {
  6. config.setAuthorizationListener(new AuthorizationListener() {
  7. @Override
  8. public boolean isAuthorized(HandshakeData data) {
  9. String userId = data.getSingleUrlParam("userId");
  10. String pageSign = data.getSingleUrlParam("pageSign");
  11. String token = data.getSingleUrlParam("token");
  12. System.out.println("userId:" + userId + ",pageSign:" + pageSign + ",token: " + token);
  13. return true;
  14. }
  15. });
  16. }

四、启用netty-socket.io注解功能;

只有打开了SpringAnnotationScanner,netty-socket.io的注解才会生效。

  1. /**
  2. * 开启netty socketio的注解功能
  3. * @param socketServer
  4. * @return
  5. */
  6. @Bean
  7. public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
  8. return new SpringAnnotationScanner(socketServer);
  9. }

五、通过校验的client连接保存下来;

保存client的时候,标识是哪个用户在哪个页面发起的连接,以便后续给指定用户的指定页面发送消息。注意:未处理同一个用户同时在多个浏览器登录的情况(可将token作为连接标识的一部分)。

  1. @OnConnect
  2. public void onConnect(SocketIOClient client) {
  3. this.socketClientComponent.storeClientId(client);
  4. System.out.println("客户端连接:" + getParamsFromClient(client));
  5. }

六、client断开连接时,从已连接池中移除掉;

  1. @OnDisconnect
  2. public void onDisconnect(SocketIOClient client) {
  3. this.socketClientComponent.delClientId(client);
  4. System.out.println("客户端断开:" + getParamsFromClient(client));
  5. }

七、client保存说明;

有效client目前是根据userId+pageSign作为连接唯一标识,将client对象保存在本地缓存中。本地缓存有撑爆的可能,正确的做法应该是同一个用户在同一个浏览器登录中,不管在多少个页面下,使用的是同一个socket。根据不同eventName事件名称来区分不同页面。服务端通过socketIoClient的sessionId来获取到真实的socketIoClient对象(socketIOServer.getClient(client.getSessionId()))。

  1. /**
  2. * socketio client 操作组件
  3. * @author haishui211
  4. */
  5. @Component
  6. public class SocketClientComponent {
  7. private Map<String, SocketIOClient> clients = new HashMap<String, SocketIOClient>();
  8. /**
  9. * 保存socketio client 客户端
  10. * @param userId
  11. * @param client
  12. */
  13. public void storeClientId(SocketIOClient client) {
  14. clients.put(getKeyFromClient(client), client);
  15. }
  16. /**
  17. * 移除socketio client 客户端
  18. */
  19. public void delClientId(SocketIOClient client) {
  20. clients.remove(getKeyFromClient(client));
  21. }
  22. /**
  23. * 给指定client发送指定事件的数据
  24. * @param businessName
  25. * @param data
  26. */
  27. public void send(String userId, String pageSign, String businessName, Map<String, Object> data) {
  28. SocketIOClient client = clients.get(getKey(userId, pageSign));
  29. if(client != null) {
  30. client.sendEvent(businessName, data);
  31. }
  32. }
  33. private String getKeyFromClient(SocketIOClient client) {
  34. HandshakeData data = client.getHandshakeData();
  35. String userId = data.getSingleUrlParam("userId");
  36. String pageSign = data.getSingleUrlParam("pageSign");
  37. return getKey(userId, pageSign);
  38. }
  39. private String getKey(String userId, String pageSign) {
  40. return "userId:" + userId + ":pageSign:" + pageSign;
  41. }
  42. }

八、testController模拟消息发送;

  1. @RestController
  2. @RequestMapping("/test")
  3. public class TestController {
  4. @Autowired
  5. private SocketClientComponent socketClientComponent;
  6. @PostMapping("/push")
  7. public void push(@RequestBody Map<String, Object> data) {
  8. String eventName = (String) data.get("eventName");
  9. String userId = (String) data.get("userId");
  10. String pageSign = (String) data.get("pageSign");
  11. socketClientComponent.send(userId, pageSign, eventName, data);
  12. }
  13. }

九、页面客户端;

  1. 1、引用的Js;
  2. <script
  3. src="http://code.jquery.com/jquery-3.4.1.js"
  4. integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
  5. crossorigin="anonymous"></script>
  6. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
  7. 2、连接发起;
  8. var socket = io.connect('http://localhost:9999?userId=12311&pageSign=firstPage&token=1234');
  9. socket.on('connect', function() {
  10. output('<span class="connect-msg">成功连接到服务端!</span>');
  11. });
  12. socket.on('testEvent', function(data) {
  13. output(JSON.stringify(data));
  14. });
  15. socket.on('disconnect', function() {
  16. output('<span class="disconnect-msg">The client has disconnected!</span>');
  17. });

十、测试数据;

  1. {
  2. "hhhh":"1234",
  3. "eventName":"testEvent",
  4. "pageSign":"firstPage",
  5. "userId":"12311"
  6. }

结果:

十一、demo地址;

https://github.com/haishui211/springRep.git

项目名:nettySocketIoDemo001,html页面放在了static目录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/83555
推荐阅读
相关标签
  

闽ICP备14008679号