简单记录一下webSocket服务端的简单使用的介绍

webScoket的简单使用demo讲解

(1) webSocket定义

          WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。

          WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

(2)再了解一下什么是长连接和短链接(可以提前了解一下什么是三次握手和四次挥手)

长连接
长连接,也叫持久连接,在TCP层握手成功后,不立即断开连接,并在此连接的基础上进行多次消息(包括心跳)交互,直至连接的任意一方(客户端OR服务端)主动断开连接,此过程称为一次完整的长连接。

短连接
          短连接,顾名思义,与长连接的区别就是,客户端收到服务端的响应后,立刻发送FIN消息,主动释放连接。也有服务端主动断连的情况,凡是在一次消息交互(发请求-收响应)之后立刻断开连接的情况都称为短连接。

1.什么时候用长连接,短连接?

1、需要频繁交互的场景使用长连接,如即时通信工具(微信/QQ,QQ也有UDP),相反则使用短连接,比如普通的web网站,只有当浏览器发起请求时才会建立连接,服务器返回相应后,连接立即断开。

2、维持长连接会有一定的系统开销,用户量少不容易看出系统瓶颈,一旦用户量上去了,就很有可能把服务器资源(内存/CPU/网卡)耗尽,所以使用需谨慎。

(3) WebSocket 方法和事件

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发
方法描述
Socket.send()使用连接发送数据
Socket.close()关闭连接

(4)Spring整合webSocket

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
(1)首先WebSocketConfiguration
@Configuration
@EnableWebSocket
public class WebSocketConfiguration {

		
	//发送消息的大小限制	
    private static final int MAX_MESSAGE_SIZE = 100 * 100 * 1024;
    //session空闲会话超时设置
    private static final long MAX_IDLE = 60 * 60 * 1000;

    /**
     * ServerEndPointExporter,在springboot内置容器(嵌入式容器)中运行时,必须上下文提供ServerEndpointExporter
     * 但是在tomcat容器中运行时,扫描工作会交给容器处理,不需要bean注入,因此下面这段代码旨在开发库中存在,并没有合并提交的过程库
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    @Bean
    public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
        container.setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
        container.setMaxSessionIdleTimeout(MAX_IDLE);
        return container;
    }

}
(2)首先webSocketService demo
@ServerEndpoint("/app/websocket/server")
@Component
public class WebsocketServer {

    StartService startService = SpringContext.getBean("startService", StartService.class);

    private static ZSmartLogger logger = ZSmartLogger.getLogger(WebsocketServer.class);

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        logger.info("onMessage: {}", message);
        message = StringUtils.trim(message);
        if (StringUtils.isEmpty(message)) {
            return;
        }
        else if ("ping".equalsIgnoreCase(message)) {
            try {
                session.getBasicRemote().sendText("pong");
            }
            catch (Exception e) {
                logger.warn("Send pong error, e: {}", e.getMessage());
            }
        }
        else {
            session.getBasicRemote().sendText("Received your message-{" + message + "}, please go on!");
        }
        startService.storeMessage(message);
    }

    @OnOpen
    public void onOpen(Session session) {
        String flowNo = getFlowNo(session);
        if (StringUtils.isNotEmpty(flowNo)) {
            startService.setSession(flowNo, session);
        }
        logger.info("Client connected, flowNo: {}.", flowNo);
    }

    @OnClose
    public void onClose(Session session) {
        String flowNo = getFlowNo(session);
        if (StringUtils.isNotEmpty(flowNo)) {
            startService.removeSession(flowNo);
        }
        logger.info("WebsocketServer.onClose start...Connection closed");
    }

    @OnError
    public void onError(Session session, Throwable error) {
        String flowNo = getFlowNo(session);
        if (StringUtils.isNotEmpty(flowNo)) {
            startService.removeSession(flowNo);
        }
        logger.warn("WebsocketServer on error, exception = {}.", error);
    }

    private String getFlowNo(Session session) {
        Map<String, List<String>> requestParams = session.getRequestParameterMap();
        List<String> flowNoArry = requestParams.get("flowNo");
        String flowNo = null;
        if (CollectionUtils.isNotEmpty(flowNoArry)) {
            flowNo = flowNoArry.get(0);
        }
        return flowNo;
    }
}
(3)start Service 先将session设置到内存,断开连接的时候从内存中删除
@Component
public class StartService {

    private static Map<String, Session> map = new HashMap<>();

    private static List<Map<String, String>> list = new ArrayList<>();

    private static ZSmartLogger logger = ZSmartLogger.getLogger(StartService.class);

    public void setSession(String flowNo, Session session) {
        logger.info("setSession, flowNo: {}.", flowNo);
        map.put(flowNo, session);
    }

    public void removeSession(String flowNo) {
        map.remove(flowNo);
    }

    public void start() throws IOException {
        logger.info("start.");
        for (Map.Entry<String, Session> entrySet: map.entrySet()) {
            Session session = entrySet.getValue();
            session.getBasicRemote().sendText("start");
            logger.info("start flowNo: {}, value: {}.", entrySet.getKey(), entrySet.getValue());
        }
    }

    public void dispatch() throws IOException {
        logger.info("dispatch.");
        for (Map.Entry<String, Session> entrySet: map.entrySet()) {
            Session session = entrySet.getValue();
            session.getBasicRemote().sendText("dispatch");
            logger.info("dispatch flowNo: {}, value: {}.", entrySet.getKey(), entrySet.getValue());
        }
    }

    public void storeMessage(String message) {
        logger.info("storeMessage, message-{}.", message);
        Map<String, String> msgMap = new HashMap<>();
        if (message.startsWith("data:")) {
            msgMap.put("type", "image");
        }
        else {
            msgMap.put("type", "text");
        }
        msgMap.put("content", message);
        list.add(msgMap);
    }

    public List<Map<String, String>> fetchMessage() {
        logger.info("fetchMessage.");
        List<Map<String, String>> newList = new ArrayList(list);
        list.clear();
        return newList;
    }
}

如果有问题欢迎指正!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值