在理解Socket之前,首先需要理解TCP/IP(传输控制协议/网间协议)和UDP(用户数据报协议)。两者是属于相对应的关系。
Socket在其中则作为一个接口的职责。在用户进程与TCP/IP之间充当中介角色。也就是说,可以将Socket理解为一个TCP/IP的接口服务,与之对接时传输数据时,只需要理解接口即可。这也就是编程语言中常说的:面向接口编程。
扩展:Socket和Http之间的使用场景。
1.首先Http属于简单的对象访问协议,常用于B/S之间的通信.主要用于应用层。例如常见的Web页面,用户界面对应前端,数据操作对应服务端。其请求只能由前端发起,服务端被动接收请求,通过内部逻辑处理后进行返回。
2.Socket是对TCP/IP协议的封装。注意:Socket本身不是一种协议.它是一个调用API
例如常见的人工客服系统。我们可以经常看到一些APP的人工客服功能上,用户会通过输入一些关键字后发送到服务端,服务端进行数据处理后返回用户想要的答案。如果使用HTTP协议,用户的每次提问都将会产生一次服务连接。如果用户量过大,发起的HTTP连接将以倍数增长。服务端的压力十分巨大。采用Socket协议可以很好的避免多次连接。当用户首次进入聊天界面后直接与Socket服务进行长连接。若用户长时间不发送消息,则断开链接(可自行设置等待消息时长)。
1.WebSocket与Socket协议都基于TCP协议,主要用于实现B/S之间的全双工通信.能更好的节省服务器资源和带宽从而达到实时通讯的目的.
2.WebSocket与Socket十分相似,前者可以开放出某个URL地址,让客户端和服务端之间建立一个类似TCP的连接,从而方便它们之间的通信.后者主要可以开放出某个端口,让客户端和服务端之间建立通信。
3.WebSocket是一种全新协议,与http不同,它的协议格式为ws://域名或IP/url
4.它与http都是应用层协议,但不同的是WebSocket可以主动向客户端发送消息。
经过上面的表述,我们对WebSocket和Socket有了一个基本的了解.下面开始讲解SpringBoot集成WebSocket的步骤
1.首先引入WebSocket的依赖到Pom文件中
org.springframework.boot
spring-boot-starter-websocket
2.在Controller的Class类中加入注解:@ServerEndpoint("url").注意:被@ServerEndpoint注解注释的类不可添加@Component。否则会导致WebSocket连接开放失败.
@ServerEndpoint("/web/socket/api")
public class WebSocketServer{
}
3.建立监听事件
@OnOpen
public void onOpen(Session session) {
log.info("客户端:{}连接成功", session.getId());
//业务代码.这里可以扩展记录本次连接的用户信息
}
@OnClose
public void onClose(Session session) {
log.info("客户端:{}连接断开", session.getId());
//业务代码
}
@OnMessage
public String onMsg(String message, Session session) {
log.info("从客户端收到消息-->:{}", message);
//业务代码
//用户记录收到消息后的事件处理
retrun "业务逻辑处理后的消息";
}
4.添加WebSocket配置类
@Slf4j
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpoint(){
return new ServerEndpointExporter();
}
}
5.启动项目后使用在线WebSocket网站测试:websocket在线测试
6.补充,个人测试时.使用了@ServerEndpoint后,无法注入Spring管理的类,例如一些业务的Service接口都无法通过Autowired注解注入.此时可通过上下文对象实例的方式进行Bean注入。
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
ApplicationContextProvider.applicationContext = applicationContext;
}
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
*
* @param clazz
* @param
* @return
*/
public static T getBean(Class clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param
* @return
*/
public static T getBean(String name, Class clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
private final IWebSocketService socketService = ApplicationContextProvider.getBean(IWebSocketService.class);