Socket.Io与WebSockt
Posted 奔跑中的程序猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Socket.Io与WebSockt相关的知识,希望对你有一定的参考价值。
H5的即时通讯技术WebSocket与Socket.Io
什么是WebSocket?
Websocket是html5新增的一种全双工通信协议,客户端和服务端基于TCP握手连接成功后,两者之间就可以建立持久性的连接,实现双向数据传输。传统HTTP和Websocket的异同不同点
1. HTTP是单向数据流,客户端向服务端发送请求,服务端响应并返回数据;Websocket连接后可以实现客户端和服务端双向数据传递。
2. 由于是新的协议,HTTP的url使用"http//"或"https//"开头;Websocket的url使用"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的主要内容,如果未能解决你的问题,请参考以下文章
socket.io 服务器能否与非 socket.io 客户端通信
将 pm2 的集群模块与 socket.io 和 socket.io-redis 一起使用