精华内容
下载资源
问答
  • 文章目录sockjs介绍产生的原因环境搭建springboot整合sockjs使用场景聊天室开发点对点通信...今天小编带大家通过一个案例使用下升级版的websocket。 sockjs介绍 So长江J算是一个浏览器库,它提供了一个跨浏览器的api...


    上一章节我们说了websocket的优缺点,我们通过websocket和http的对比分析,总结出用websocket的场景。今天小编带大家通过一个案例使用下升级版的websocket。

    sockjs介绍

    So长江J算是一个浏览器库,它提供了一个跨浏览器的api , 他在浏览器和服务端建立了一个低延迟、全双工、跨域通信通道。

    产生的原因

    向ie这些浏览器可能缺少对websocket的支持,我们上一章节也是在谷歌浏览器下开发完成的。这里对ie这些浏览器没有做测试,但是一些低版本的浏览器的确是不支持的websocket的。
    sockJs对浏览器兼容性很大。在原声的websocket基础上进行了优化。sockjs在不支持websocket的浏览器上会采用轮询的方式实现双向通信。

    环境搭建

    springboot整合sockjs

    springboot 对sockjs支持性很良好。只需要在原有的websocket配置上添加已sockjs方式发布就可以了。

    
    @Configuration
    //注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样
    @EnableWebSocketMessageBroker
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer   {
    
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {//注册STOMP协议的节点(endpoint),并映射指定的url
            //注册一个STOMP的endpoint,并指定使用SockJS协议
            registry.addEndpoint("/endpointAric")
                    .setAllowedOrigins("*")
                    .addInterceptors(createSessionInterceptor())
                    .withSockJS();
    
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(Message Broker)
            //广播式应配置一个/topic消息代理
            registry.enableSimpleBroker("/topic", "/queue");
            //registry.setApplicationDestinationPrefixes("/app");
            //点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/
            registry.setUserDestinationPrefix("/user/");
    
        }
    
        /**
         * 配置客户端入站通道拦截器
         */
        @Override
        public void configureClientInboundChannel(ChannelRegistration registration) {
            registration.setInterceptors(createUserInterceptor());
    
        }
    
    
        @Bean
        public HandshakeInterceptor createSessionInterceptor(){
            return new SessionAuthHandshakeInterceptor();
        }
        /*将客户端渠道拦截器加入spring ioc容器*/
        @Bean
        public UserInterceptor createUserInterceptor() {
            return new UserInterceptor();
        }
    
    
        @Override
        public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
            registration.setMessageSizeLimit(500 * 1024 * 1024);
            registration.setSendBufferSizeLimit(1024 * 1024 * 1024);
            registration.setSendTimeLimit(200000);
        }
    }
    
    

    registry.enableSimpleBroker("/topic", "/queue");设置的topic,queue就是客户端和服务端的通信通道。

    使用场景

    本节内容我们将通过聊天室体验下websocket的使用。

    聊天室开发

    上面我们已经配置了服务端的环境,这样我们就可以开发通道内的通信内容。聊天室使用websocket进行通信解决了我们通过ajax调用的实时性。保证了消息的准确性。无延后性。

    点对点通信

    
    /*点对点通信*/
    @MessageMapping(value = "/sendToUser")
    public void templateTest1(@Payload  String message, @Header("userId") String userId,
                              @Headers Map<String, Object> headers) {
        int i = 1;
        for (SimpUser user : userRegistry.getUsers()) {
            System.out.println("用户" + i++ + "---" + user);
        }
        CustomUser userInfo = (CustomUser) ((Map)(headers.get("simpSessionAttributes"))).get(CoreConstants.USERINFO);
        String fromUserId = String.valueOf(userInfo.getUserId());
        //发送消息给指定用户
        messagingTemplate.convertAndSendToUser(userId, "/queue/message",new AricResponse(fromUserId,userId,message));
        if (!fromUserId.equals(userId)) {
            //给自己发送一条,消息同步
            messagingTemplate.convertAndSendToUser(fromUserId, "/queue/message",new AricResponse(fromUserId,userId,message));
        }
        //消息新增
        messageService.insertBackMessage(fromUserId,userId,message);
    }
    
    

    @MessageMapping(value = "sendToUser") 该注解实现了接受客户端的请求。对应客户端可以通过
    stompClient.send("/sendToUser", {'userId': userId},content);进行发送至服务端,userId是客户端用户发送给指定用户的id, content是发送的内容
    服务端通过@Payload和@Header注解接受前端传送的信息。上述代码中获取发送者用户id的地方为什么那么写呢。下面我们看看客户端连接的方式

    
    // 建立连接对象(还未发起连接)
        socket = new SockJS(host+"/endpointAric");
    
        // 获取 STOMP 子协议的客户端对象
        stompClient = Stomp.over(socket);
    
        // 向服务器发起websocket连接并发送CONNECT帧
        stompClient.connect(
            {
                userId: currentUser.userId // 携带客户端信息
            },
            function connectCallback(frame) {
                // 连接成功时(服务器响应 CONNECTED 帧)的回调方法
                subscribe();
                console.log("连接成功");
            },
            function errorCallBack(error) {
                // 连接失败时(服务器响应 ERROR 帧)的回调方法
                console.log("连接失败"+error);
                if (errorTimes < 10) {
                    errorTimes++;
                    setTimeout("connect();",8000);
                }
            }
        );
    
    

    在连接的时候客户端会将当前用户的id传递进来,这里也解释了为什么服务端那样获取用户信息。然后就通过/queue/message发送给指定的用户。因为我们在配置websocket的时候指定了
    registry.setUserDestinationPrefix("/user/");,所以服务端发送给/queue/message了,客户端订阅的时候需要加上user 即 /user/queue/message

    
    function subscribe() {
        stompClient.subscribe('/user/queue/message', function (response) {
            var returnData = JSON.parse(response.body);
            if (returnData.fromUserId == returnData.toUserId) {
                //自己发送的消息需要自己渲染到聊天框中
                setMessageInnerHTML(currentUser.userId, returnData, 0);
            } else if (returnData.fromUserId == currentUser.userId) {
                //自己发送信息给别,自己收到的信息
                setMessageInnerHTML(returnData.toUserId, returnData, 1);
            } else {
                //别人发送的信息
                setMessageInnerHTML(returnData.fromUserId, returnData, 0);
            }
        });
    }
    
    

    群聊

    
    /**
     * 多房间聊天室
     * @param chatRoomId
     * @param message
     * @return
     */
    @MessageMapping("/welcome/{chatRoomId}") //当浏览器向服务端发送请求时,通过@MessageMapping映射/welcome这个地址,类似于@ResponseMapping
    @SendTo("/topic/getResponse/{chatRoomId}")//当服务器有消息时,会对订阅了@SendTo中的路径的浏览器发送消息
    public AricResponse say(@Header("userId") String userId,@DestinationVariable("chatRoomId") String chatRoomId, AricMessage message) {
    
        try {
            //睡眠1秒
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AricResponse(userId,null,"welcome," + message.getName()+chatRoomId + "!");
    }
    
    

    群聊相对与单聊简单很多,我们发送信息的时候只需要发送到房间通道内就行。而在次群聊内的人只需要订阅房号的信息就行了。这里代码不在赘述。有疑问的小伙伴可以通过下方加入战队找到我。

    效果

    私聊界面

    总结

    sockjs在websocket基础上进行各个浏览器的兼容,让我们的开发变得友好起来。
    如果你使用Java做服务端,同时又恰好使用Spring Framework作为框架,那么推荐使用SockJS,因为Spring Framework本身就是SockJS推荐的Java Server实现,同时也提供了Java 的client实现。

    如果你使用Node.js做服务端,那么毫无疑问你该选择Socket.IO,它本省就是从Node.js开始的,当然服务端也提供了engine.io-server-java实现。甚至你可以使用

    加入战队

    微信公众号

    微信公众号
    封面

    展开全文
  • 连接本地websocket服务延迟的问题

    千次阅读 2017-06-12 23:18:00
    今天用C#编写了一个Chrome Remote Debugger的客户端程序,发现使用rest和websocket程序时第一次连接的时候特别慢,大概每次都要消耗一秒左右,而用chrome直接连接却没有这种情况。 由于后续编写蜘蛛时也经常要调试...

    今天用C#编写了一个Chrome Remote Debugger的客户端程序,发现使用rest和websocket程序时第一次连接的时候特别慢,大概每次都要消耗一秒左右,而用chrome直接连接却没有这种情况。

    由于后续编写蜘蛛时也经常要调试,每次多消耗两秒觉得开销有点大,便准备着手解决它。

    最开始以为是webproxy的问题,后来查看了一下,确实没有代理。便用Fiddler模拟了一下rest请求试了一下,它也需要一秒左右。便对比了一下chrome和fiddler的请求包,发现Request的Url有所不同:

    于是便将程序中的请求也改成了127.0.0.1,我的程序便也变快了。

    解决了问题后,回头来再分析一下原因,最开始以为是我的dns解析出问题了,试了一下,解析localhost是很快的,地址也是正常的。于是我便自己写了一个websocket server自己尝试连接了一下试试,发现出现了同样的现象:服务器和客户端一个使用localhost,一个使用127.0.0.1的时候,就会出现一秒左右的连接延迟,一致的时候就是正常的

    看来这个并不是Server端Chrome的问题,解决方式也知道了。至于是不是协议规定的,目前还没有时间详细研究,后续有空再继续研究一下。

    展开全文
  • WebSocket

    2021-04-07 23:54:14
    WebSocket Socket是什么? HTML5 和 WebSocket WebSocket优点 HTTP WebSocket WebSocket 属性 WebSocket 事件 WebSocket 方法 websocketpp 介绍 示例工程 参考 Socket是什么? Socket是应用层与TCP/IP协议...
    WebSocket

    本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

    Socket是什么?

    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

    HTML5 和 WebSocket

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
    WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
    在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

    WebSocket优点

    HTTP

    • 一条连接上只可以发送一个请求

    • 请求只能从客户端开始。客户端不可以接收除了响应以外的指令。

    • 请求 / 响应首部未经过压缩就直接进行传输。首部的信息越多,那么延迟就越大。

    • 发送冗长的首部。每次互相发送相同的首部造成的浪费越多

    • 可以任意选择数据压缩格式。非强制压缩发送

    WebSocket

    • 推送功能
      支持服务器端向客户端推送功能。服务器可以直接发送数据而不用等待客户端的请求。
    • 减少通信量
      只要建立起websocket连接,就一直保持连接,在此期间可以源源不断的传送消息,直到关闭请求。也就避免了HTTP的非状态性。
      和http相比,不但每次连接时的总开销减少了,而且websocket的首部信息量也小 ,通信量也减少了。
    • 减少资源消耗

    WebSocket 属性

    属性描述
    Socket.readyState只读属性 readyState 表示连接状态,可以是以下值:
    0 - 表示连接尚未建立。
    1 - 表示连接已建立,可以进行通信。
    2 - 表示连接正在进行关闭。
    3 - 表示连接已经关闭或者连接不能打开。
    Socket.bufferedAmount只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    WebSocket 事件

    事件事件处理程序描述
    openSocket.onopen连接建立时触发
    messageSocket.onmessage客户端接收服务端数据时触发
    errorSocket.onerror通信发生错误时触发
    closeSocket.onclose连接关闭时触发

    WebSocket 方法

    方法描述
    Socket.send()使用连接发送数据
    Socket.close()关闭连接HTML5 WebSocket

    websocketpp

    介绍

    websocketpp是一个只有头文件的支持websocket协议的C++开源库,支持websocket客户端和服务器功能,网络传输模块基于boost::asio。
    提供 server 功能的 websocketpp::server 和提供 client 功能的 websocketpp:client 都继承自基类 websocketpp::endpoint , endpoint提供了一些通用的功能函数:

    void set_access_channels(log::level channels);//设置日志级别
    void clear_access_channels(log::level channels)//屏蔽某个级别的日志
    
    void set_open_handler(open_handler h)//设置打开连接时的回调函数
    void set_close_handler(close_handler h)//设置关闭连接时的回调函数
    void set_fail_handler(fail_handler h)//设置连接失败时的回调函数
    void set_message_handler(message_handler h)//设置收到消息时的回调函数
    

    示例工程

    web-socket-test

    参考

    HTML5 WebSocket

    html5-websocket初探

    WebSocket协议及优点

    展开全文
  • 基于spring boot + netty实现性能的websocket

    前言

    之前已经介绍了多种websocket的实现方式,但是底层网络请求都是由tomcat进行处理的。我们都知道netty在网络请求处理上有更好的性能。那么我们的websocket能否基于netty来实现呢?
    本文将教你如何基于Netty搭建高性能Websocket服务器。


    一、项目结构

    在这里插入图片描述
    说明:
    基于spring boot新建工程netty-websocket。

    二、代码说明

    1.maven依赖

    <dependencies>
            <dependency
    展开全文
  • websocket

    2020-03-26 21:25:07
    WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。 在2008年诞生,2011年成为国际标准。 现在基本所有浏览器都已经支持了。 WebSocket是一种在单个TCP连接上进行...
  • Websocket

    2019-02-19 17:37:45
    New Document 看完让你彻底搞懂Websocket原理 https://www.toutiao.com/i6658478665484993037/ 一、websocket与http ...
  • webSocket

    2018-09-05 09:30:15
    /websocket",configurator=GetHttpSessionConfigurator.class) public class WebSocketUtil { //用来存放每个客户端对应的WebSocketTest对象,适用于同时与多个客户端通信 public static CopyOnWr...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,609
精华内容 5,443
关键字:

websocket延迟高