Socket.Io与WebSockt

Posted 奔跑中的程序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Socket.Io与WebSockt相关的知识,希望对你有一定的参考价值。

H5的即时通讯技术WebSocket与Socket.Io

什么是WebSocket?

Websockethtml5新增的一种全双工通信协议,客户端和服务端基于TCP握手连接成功后,两者之间就可以建立持久性的连接,实现双向数据传输。传统HTTPWebsocket的异同不同点

1. HTTP是单向数据流,客户端向服务端发送请求,服务端响应并返回数据;Websocket连接后可以实现客户端和服务端双向数据传递。

2. 由于是新的协议,HTTPurl使用"http//""https//"开头;Websocketurl使用"ws//"开头

相同点

1都需要建立TCP连接

2都是属于七层协议中的应用层协议应用层 表示层 会话层 传输层 网络层 链路层 物理层

 

什么是Socket.io

实际应用中,如果需要Websocke进行双向数据通信,Socket.io是一个非常好的选择。其实github上面也有通过JS封装好的Websocket库,ws可用于client和基于node搭建的服务端使用,但是用起来相对繁琐,star相对Socket.io较少,所以不推荐使用。

Socket.io不是Websocket,它只是将Websocket和轮询 (Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。socket.io支持4种协议:["websocket" , "htmlfile" , "xhr-polling" , "jsonp-polling"]也就是说,Websocket仅仅是 Socket.io实现实时通信的一个子集。因此Websocket客户端连接不上Socket.io服务端,当然Socket.io客户端也连接不上Websocket服务端。


 

Socket.Io举例

下面我举一个例子,socket.Io如何与前端进行交互

Java端实现代码

使用 Spring Boot 2.0进行开发主要依赖为:

<dependency>

            <groupId>com.corundumstudio.socketio</groupId>

            <artifactId>netty-socketio</artifactId>

<version>1.7.18</version>

</dependency>

 

 

@Service(value = "socketioservice")

@Profile("socketIO")

@Slf4j

public class SocketIOServiceImpl implements SocketIOService {

 

 

 

    @Autowired

    FilterFactory filterFactory;

    

    private static final String GROUPID="groupId";

    private static final String CLIENT_ID="clientId";

 

    //需要注入,否则无效

    @Autowired

    private SocketIOServer socketIoServer;

 

 

    private  static final ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>();

 

   

    @PostConstruct

    private void init() {

            socketIoServer.start();

    }

 

 

    /**

     * 客户端连接的时候触发

     *

     * @param client

     */

    @OnConnect

    public void onConnect(SocketIOClient client) {

UUID sessionID = client.getSessionId();

String groupId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.GROUPID);

String clientId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.CLIENT_ID);

socketIOClientMap.put(clientId, client);


PushMessage mess = new PushMessage();

log.info("连接成功 sessionID:{}, clientid:{},groupId:{} ,client.getRemoteAddress:{}", sessionID.toString(), clientId, groupId,client.getRemoteAddress());

mess.setResult(true);

mess.setResultMessage("连接成功");

// 回发消息 消息发送成功

client.sendEvent("push_event", mess);

log.info("发送数据成功");

    }

 

    /**

     * 客户端关闭连接时触发

     *

     * @param client

     */

    @OnDisconnect

    public void onDisconnect(SocketIOClient client) {

    String groupId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.GROUPID);

    String clientId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.CLIENT_ID);

    socketIOClientMap.remove(clientId);

    socketFilter.remove(clientId+"^"+groupId);

        log.info("客户端sessionid:{}断开连接 clientId:{}", client.getSessionId(),client);

    }

 

    /**

     * 客户端事件

     * 注册过滤器信息

     * @param client   客户端信息

     * @param request 请求信息

     * @param data     客户端发送数据

     */

    @OnEvent(value = "push_event")

    public void onEvent(SocketIOClient client, AckRequest request, PushMessage data) {

    String groupId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.GROUPID);

    String clientId=client.getHandshakeData().getSingleUrlParam(SocketIOServiceImpl.CLIENT_ID);

    log.info("前端过滤器内容为:{}",data.getContent());

    log.info("groupID:{}",groupId);

   

    }

 

        

 

} 

 

@Data

@EqualsAndHashCode(callSuper = false)

@Accessors(chain = true)

public class PushMessage {

 

    /**

     * 用户ID

     */

    private String userID;

 

 

    private String content;

 

    /**

     * 消息结果:1:成功  0:失败

     */

    private boolean result;

 

    /**

     * 处理结果消息提示

     */

    private String resultMessage;

 

    /**

     * 操作类型

     */

    private String optType;

 

    /**

     * 窗口id

     */

    private String winId;

 

}

 

 

package com.zznode.web.sokect;

 

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Profile;

 

import com.corundumstudio.socketio.SocketConfig;

import com.corundumstudio.socketio.SocketIOServer;

import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;

 

@Configuration

@ConfigurationProperties(prefix = "socketio",ignoreUnknownFields = false,ignoreInvalidFields =true)

@Profile("socketIO")

public class SocketIOConfig {

 

    @Value("${socketio.port}")

    private Integer port;

 

    @Value("${socketio.bossCount}")

    private int bossCount;

 

    @Value("${socketio.workCount}")

    private int workCount;

 

    @Value("${socketio.allowCustomRequests}")

    private boolean allowCustomRequests;

 

    @Value("${socketio.upgradeTimeout}")

    private int upgradeTimeout;

 

    @Value("${socketio.pingTimeout}")

    private int pingTimeout;

 

    @Value("${socketio.pingInterval}")

    private int pingInterval;

    

 

 

 

public void setPort(Integer port) {

this.port = port;

}

 

 

public void setBossCount(int bossCount) {

this.bossCount = bossCount;

}

 

 

public void setWorkCount(int workCount) {

this.workCount = workCount;

}

 

 

public void setAllowCustomRequests(boolean allowCustomRequests) {

this.allowCustomRequests = allowCustomRequests;

}

 

 

public void setUpgradeTimeout(int upgradeTimeout) {

this.upgradeTimeout = upgradeTimeout;

}

 

 

public void setPingTimeout(int pingTimeout) {

this.pingTimeout = pingTimeout;

}

 

 

public void setPingInterval(int pingInterval) {

this.pingInterval = pingInterval;

}

 

 

/**

     * 以下配置在上面的application.properties中已经注明

     * @return

     */

    @Bean

    public SocketIOServer socketIOServer() {

SocketConfig socketConfig = new SocketConfig();

 

com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();

config.setSocketConfig(socketConfig);

config.setPort(port);

config.setBossThreads(bossCount);

config.setWorkerThreads(workCount);

config.setAllowCustomRequests(allowCustomRequests);

config.setUpgradeTimeout(upgradeTimeout);

config.setPingTimeout(pingTimeout);

config.setPingInterval(pingInterval);

 return new SocketIOServer(config);

    }

    

   

/**

 * 用于扫描netty-socketio的注解,比如 @OnConnect、@OnEvent

 * @return

 */

@Bean

public SpringAnnotationScanner springAnnotationScanner() {

return new SpringAnnotationScanner(socketIOServer());

}

}

前端连接代码

 

数据监听函数socket.on('push_event', function (data) {

      alert('push_event 推送的数据为:'+data.resultMessage);

  });

第一个参数为监听的事件名称,第二个返回数据回调函数。

 

 

<!DOCTYPE html>

<html>

<body>

</body>

</html>

<script ></script>  <!--我这把js放在本地了,可以去 https://www.bootcdn.cn/socket.io/ 下载-->

<script>

  var socket = io.connect('http://127.0.0.1:8001?groupId=fty001&clientId=c001');   

  alert("连接....");

  

  socket.on('connect', function () { alert("成功连接");});

   

 // asss=" <filters> <filter name=\"全量告警\"> <sql name=\"sql\" relRuleType=""/> </filter> </filters> ";

  

  socket.emit("push_event",{"content":"<filters> <filter name=\"全量告警\"> <sql name=\"sql\" relRuleType=\"\"/> </filter> </filters>"});

  

  socket.on('disconnect', function () {alert("断开"); });

  

 

  

   socket.on('push_event', function (data) {

      alert('push_event 推送的数据为:'+data.resultMessage);

  });

  

  

  

</script>


以上是关于Socket.Io与WebSockt的主要内容,如果未能解决你的问题,请参考以下文章

从android与socket.io通信

一次与两个用户随机聊天(Socket.io)

socket.io 服务器能否与非 socket.io 客户端通信

将 pm2 的集群模块与 socket.io 和 socket.io-redis 一起使用

RxJS.fromWebSocket 与 Socket.io

GraphQL 订阅与 socket.io