Web端即时通信技术-WebSocket

32 篇文章 1 订阅
订阅专栏

最近在做项目的时候,遇到了一个前端页面需要实时刷新的功能,一种方法是我们通过短轮询的方式,但这种方式虽然简单,但是无用的请求过多,占用资源,并且如果是对数据要求高较高的场景,就不适用了。

 

这个时候就要考虑应用长连接了,最开始想到的是,Http1.1以后支持的长连接,但是经过实践后发现,这里可能存在一个误解:Http协议是基于请求/响应模式的,因此客户端请求后只要服务端给了响应,本次Http请求就结束了,没有长连接这么一说,那么自然也就没有短连接这么一说了。也就是说,在这样一个HTTP连接中,可以发送多个Request,接收多个Response。但是Request和Response永远是相对应的,也就是说一个request只能有一个response。并且这个response也是被动的,不能主动发起。

所谓的HTTP长连接和短连接,其实本质上说的是TCP连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才有真正的长连接和短连接这么一说。

那么下面我们一起来看下WebSocket是如何实现的。

什么是WebSocket?

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

这里先来区分下三者的含义:

  • 单工:数据传输只允许在一个方向上传输,只能一方发送数据,另一方来接受数据并发送;例如:对讲机。

  • 半双工:数据传输允许两个方向上的传输,但是同一时间内,只可以有一方发送或接收消息,并存在最大传输距离的限制。

  • 全双工:接口可以同时发送和接收数据,最大吞吐量可达到双倍速率,且消除了半双工的物理距离限制。

解决了什么问题?

客户端(浏览器)和服务器进行通信,只能由客户端发起ajax请求,才能进行通信,服务端无法主动向客户端推送消息。像我们常见的一些场景:体育赛事、聊天室、实时位置之类的场景时,客户端要获取服务器端的变化,就只能通过轮询(定时请求)的方式来了解服务器端有没有新的信息变化

轮询效率低,非常浪费资源(需要不断的发送请求,不停连接服务器)

WebSocket的出现,让服务器端可以主动向客户端发送信息,使得浏览器具备了实时双向通信的能力。

实现案例:

前端示例:

// websocket.js   
const WebSocket = require('ws')
const events = []
let latestTimestamp = Date.now()
const clients = new Set()//连接着的socket数组

const EventProducer = () => {
  const event = {
    id: Date.now(),
    timestamp: Date.now()
  }
  events.push(event)
  latestTimestamp = event.timestamp
  
  // 推送给所有连接着的socket
  clients.forEach(client => {
    client.ws.send(JSON.stringify(events.filter(event => event.timestamp > client.timestamp)))
    client.timestamp = latestTimestamp
  })
}

// 每10秒生成一个新的事件
setInterval(() => {
  EventProducer()
}, 10000)

// 启动socket服务器
const wss = new WebSocket.Server({ port: 8080 })
wss.on('connection', (ws, req) => {
  console.log('client connected')
  // 首次连接,推送现存事件
  ws.send(JSON.stringify(events))
  const client = {
    timestamp: latestTimestamp,
    ws,
  }
  clients.add(client)//将连接放入数组
  ws.on('close', _ => {
    clients.delete(client)
  })
})
var timestampRef={current:0}
    var eventsRef={current:[]}
     const ws = new WebSocket(`ws://localhost:8080/ws?timestamp=${timestampRef.current}`)
    ws.addEventListener('open', e => {
      console.log('successfully connected')
    })
    ws.addEventListener('close', e => {
      console.log('socket close')
    })
    ws.addEventListener('message', (ev) => {
      const latestEvents = JSON.parse(ev.data)
      if (latestEvents && latestEvents.length) {
        timestampRef.current = latestEvents[latestEvents.length - 1].timestamp
         //注意latestEvents数据是后端新生成的数据,前端需要自己拼上老数据
        eventsRef.current = [...eventsRef.current, ...latestEvents]
        console.log(eventsRef)
      }
    })

服务端代码(基于SpringBoot):

WebSocketConfig

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Resource
    private HttpAuthHandler handler;

    @Resource
    private WebSocketInterceptor interceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(handler, "/hello")
                .addInterceptors(interceptor)
                .setAllowedOrigins("*");
    }
}

HttpAuthHandler

@Component
public class HttpAuthHandler extends TextWebSocketHandler {

    /**
     * 建立成功事件
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
    }

    /**
     * 接受消息事件
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        Object token = session.getAttributes().get("token");
        System.out.println("server 接收到 " + token + " 发送的 " + payload);
        session.sendMessage(new TextMessage("server 发送给 " + token + " 消息 " + payload + " " +    LocalDateTime.now().toString()));
    }

    /**
     * 断开连接时
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

WebSocketInterceptor

public class WebSocketInterceptor implements HandshakeInterceptor {

    /**
     * 握手前
     *
     * @param request
     * @param response
     * @param wsHandler
     * @param attributes
     * @return
     * @throws Exception
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("握手开始");
        // 获得请求参数
        Map<String, String> paramMap = HttpUtil.decodeParamMap(request.getURI().getQuery(), StandardCharsets.UTF_8);
        String uid = paramMap.get("token");
        if (StrUtil.isNotBlank(uid)) {
            // 放入属性域
            attributes.put("token", uid);
            System.out.println("用户 token " + uid + " 握手成功!");
            return true;
        }
        System.out.println("用户登录已失效");
        return false;
    }

    /**
     * 握手后
     *
     * @param request
     * @param response
     * @param wsHandler
     * @param exception
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
        System.out.println("握手完成");
    }
}

测试:

上边简单实现了一个webSocket通信。实际的东西还有很多,比如webSocket扩展,心跳检测,数据加密,身份认证等知识点。但自己也需要再去研究,所以先不做介绍了。

到这里,基本上使用应该是没问题了,下面我们来继续来继续探讨下有关其实现方面的细节。

实现原理

WebSocket是位于应用层的一个应用层协议,它需要依赖HTTP协议进行一次握手,握手成功后,数据就直接从TCP通道传输,与HTTP无关了。也就是分为握手阶段和数据传输阶段,即:HTTP握手+双工的TCP连接。

下面我们分别来看一下这两个阶段的具体实现原理。

一、握手阶段

客户端发送消息:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13

在HTTP Header中设置Upgrade字段,其字段值为websocket,并在Connection字段提示Upgrade,服务端若支持WebSocket协议,并同意握手,可以返回如下结构:


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13

我们来详细讨论WebSocket握手的细节,发现除了设置Upgrade之外,还需要设置其他的Header字段。

  • Sec-WebSocket-Key:必传,由客户端随机生成的 16 字节值, 然后做 base64 编码, 客户端需要保证该值是足够随机, 不可被预测的 (换句话说, 客户端应使用熵足够大的随机数发生器), 在 WebSocket 协议中, 该头部字段必传, 若客户端发起握手时缺失该字段, 则无法完成握手

  • Sec-WebSocket-Version:必传, 指示 WebSocket 协议的版本, RFC 6455 的协议版本为 13, 在 RFC 6455 的 Draft 阶段已经有针对相应的 WebSocket 实现, 它们当时使用更低的版本号, 若客户端同时支持多个 WebSocket 协议版本, 可以在该字段中以逗号分隔传递支持的版本列表 (按期望使用的程序降序排列), 服务端可从中选取一个支持的协议版本

  • Sec-WebSocket-Protocol :可选, 客户端发起握手的时候可以在头部设置该字段, 该字段的值是一系列客户端希望在与服务端交互时使用的子协议 (subprotocol), 多个子协议之间用逗号分隔, 按客户端期望的顺序降序排列, 服务端可以根据客户端提供的子协议列表选择一个或多个子协议

  • Sec-WebSocket-Extensions:可选, 客户端在 WebSocket 握手阶段可以在头部设置该字段指示自己希望使用的 WebSocket 协议拓展

服务端若支持 WebSocket 协议, 并同意与客户端握手, 则应返回 101 的 HTTP 状态码, 表示同意协议升级, 同时应设置 Upgrade 字段并将值设置为 websocket, 并将 Connection 字段的值设置为 Upgrade, 这些都是与标准 HTTP Upgrade 机制完全相同的, 除了这些以外, 服务端还应设置与 WebSocket 相关的头部字段:

  • Sec-WebSocket-Accept:必传, 客户端发起握手时通过 | Sec-WebSocket-Key | 字段传递了一个将随机生成的 16 字节做 base64 编码后的字符串, 服务端若接收握手, 则应将该值与 WebSocket 魔数 (Magic Number) "258EAFA5-E914-47DA- 95CA-C5AB0DC85B11" 进行字符串连接, 将得到的字符串做 SHA-1 哈希, 将得到的哈希值再做 base64 编码, 最终的值便是该字段的值

  • Sec-WebSocket-Protocol:可选, 若客户端在握手时传递了希望使用的 WebSocket 子协议, 则服务端可在客户端传递的子协议列表中选择其中支持的一个, 服务端也可以不设置该字段表示不希望或不支持客户端传递的任何一个 WebSocket 子协议

  • Sec-WebSocket-Extensions:可选, 与 Sec-WebSocket-Protocol 字段类似, 若客户端传递了拓展列表, 服务端可从中选择其中一个作为该字段的值, 若服务端不支持或不希望使用这些扩展, 则不设置该字段

  • Sec-WebSocket-Version:必传, 服务端从客户端传递的支持的 WebSocket 协议版本中选择其中一个, 若客户端传递的所有 WebSocket 协议版本对服务端来说都不支持, 则服务端应立即终止握手, 并返回 HTTP 426 状态码, 同时在 Header 中设置 | Sec-WebSocket-Version | 字段向客户端指示自己所支持的 WebSocket 协议版本列表

二、数据传输阶段

通信的数据是基于帧(frame)的,可以传输文本数据,也可以直接传输二进制数据,效率高,当然,开发者相应的也需要考虑封包、拆包、编号等细节。

三、优缺点

优点:

  • 节约带宽
    不停地轮询服务端数据这种方式,使用的是http协议,head信息很大,有效数据占比低, 而使用WebSocket方式,头信息很小,有效数据占比高。

  • 实时性
    考虑到服务器压力,使用轮询方式不可能很短的时间间隔,否则服务器压力太多,所以轮询时间间隔都比较长,好几秒,设置十几秒。而WebSocket是由服务器主动推送过来,实时性是最高的。

  • 压缩效果好

  • 可以支持扩展

缺点:

  • 不兼容低版本IE

总结

WebSocket是HTML5开始提供的一种独立在单个TCP连接上进行全双工通讯的有状态协议,并且还能支持二进制帧、扩展协议、部分自定义的自协议、压缩等特性。

目前看来,WebSocket可以完美替代AJAX轮询和Comet,但是某些场景还是不能替代SSE,WebSocket和SSE各有所长。

Spring boot WebSocket 学习总结
cy1798的博客
05-05 1572
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它最初于2008年被提出,后来由IETF标准化。WebSocket协议旨在解决HTTP协议的一些限制,例如HTTP请求只能由客户发起,服务器不能主动向客户发送数据等。
python-websocket-serial:简单的 Tkinter gui 控制 websocket 到串行(反之亦然)通信
07-09
Websocket <--> 串口工具 尝试获取执行以下操作的 Python 应用程序: 创建一个 Websocket 服务器。 连接、读取和写入串行口。 提供用于用户控制的 GUI 界面。 安装 下载/克隆后,为 Python 应用程序创建一个虚拟环境来运行 virtualenv venv 激活虚拟环境 . venv/bin/activate 使用 PIP 安装依赖项 pip install -r requirements.txt 跑步 目前没有太多可展示的,一堆 Tkinter GUI、WS4PY 和串行代码的混搭示例 尝试 python anothergtest.py
Websocket即时通讯
P923284735的博客
02-17 1548
WebScoekt即时通讯
WebSocket协议及其在实时通信中的重要性
最新发布
无知而狂妄
03-02 1005
WebSocket 是一种网络传输协议。它允许客户和服务器之间进行双向通信,而不需要每次请求都重新建立连接。可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 通信始于 HTTP 握手,之后升级到WebSocket协议。双向通信WebSocket支持全双工通信,允许服务器主动向客户推送数据,而不需要客户发送请求。较低的延迟:WebSocket 通过在建立连接后保持持久连接的方式,避免了重复建立和关闭连接的开销。可以减少延迟,实现更快的数据传输和实时更新。
即时通讯WebSocket详解及使用
qq_52337177的博客
10-12 6414
即时通讯WebSocket详解及使用
【springboot进阶】springboot集成fastjson(四)优雅地接收GET请求参数并对其校验
06-18 1649
通过注解和参数解析器的方式,可以实现GET请求方式的参数进行优雅的封装注入,免去了控制器的过长参数的处理,同时有多字段的校验过于繁琐的问题。
java开发oa系统源码下载-Spring-websocket:Spring整合websocket实现即时通讯
06-05
本项目基于Spring平台,整合websocket协议,实现一个简易web聊天室的功能。主要特性如下: 1.包含聊天室登录、退出的功能。登录时,浏览器自动向服务器发起websocket连接,退出时自动切断。 2.登录后,用户可查看到...
iOS开发项目- 基于WebSocket的聊天通讯(1)
01-21
公司项目需要开发一个类似QQ、微信的即时IM聊天功能,做到实时监控消息,需要用的技术websocket。 概述WebSocket: 1.1 为什么我们需要WebSocket这样的实时的通信协议? WebSocketweb通信方式的一种,像我们...
C# websocket及时通信协议的实现方法示例
01-20
WebSocket出现之前,Web为了实现即时通讯,所用的技术都是Ajax轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服的浏览器。这种传统的...
websocket-protocol:websocket协议
05-14
这种客户是主动方,服务是被动方的传统Web模式对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应用。在WebSocket...
对于WebSocket的简单理解
qq_45511733的博客
09-26 388
一、什么是WebSocket 首先需要明白webSocket的概念,下边是维基百科的解释 WebSocket是一种通信协议,可在单个TCP连接上进行全双工通信WebSocket使得客户和服务器之间的数据交换变得更加简单,允许服务主动向客户推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。 我们都知道,不使用WebSocket与服务器实时交互,一般有两种方法。AJAX轮询和Long Polling长轮询。 AJAX轮询
Springboot实现拦截器功能
热门推荐
weixin_52875557的博客
04-11 1万+
preHandle 预先处理,在目标的controller方法执行之前,进行处理 postHandle 在目标的controller方法执行之后,进行处理 afterCompletion 在页面渲染之后进行处理方法
spring框架下基于websocket握手的拦截器配置(HandshakeInterceptor
weixin_44245778的博客
03-25 1万+
本次博客为记录小程序开发过程中遇到的问题,总结一些经验! 对于拦截器的配置,相信很多人都会碰到坑,当然遇到的坑越多,你的技能提升的越快,我觉得是对的。做项目是可以提升一个程序员的技能,考验开发能力的最好方法之一。 下面直接进入正题: 本次拦截器的配置主要是要实现在websocket握手前,对用户信息的验证及筛选。 在本系统中原先已实现了登录验证的拦截器,即判断小程序请求头中是否存在登录态...
spring webSocket 拦截
weixin_43982927的博客
03-21 4013
websocket 在进行通信的时候不会经过 普通的HandlerInterceptor 拦截器 如果要对websocket 请求做拦截处理 要创建专门的websocket 的拦截器HandshakeInterceptor /** * webSocket 握手拦截 * 建立websocket 连接 首先会发送一个http 的请求来 建立连接 * 在websocket 里面的session 不是httpsession 所以会丢失用户态信息 */ @Component public class MyW
集成websocket实现实时通信(ruoyi 使用笔记)
沉淀、分享、成长,让自己和他人都能有所收获!
06-01 1万+
Websocket 是一种基于 TCP 协议的全双工通信协议,它使得客户和服务器之间可以进行实时的双向通信。相对于传统的 HTTP 协议只能通过客户发送请求,然后等待服务的响应,WebSocket 可以让客户和服务器在任何时候都可以相互发送消息,这种实时通信的方式非常适合需要实时更新数据的应用场景,比如聊天室、在线游戏、股票行情等。客户向服务器发起 WebSocket 握手请求;服务器返回确认信息给客户,完成握手;握手成功后,客户和服务器就可以通信了;
WebSocket学习
orchidofocean的博客
02-25 980
从搜索引擎搜索资料:https://www.runoob.com/html/html5-websocket.html WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户和服务器之间的数据交换变得更加简单,允许服务主动向客户推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以...
websocket介绍以及springboot集成websocket
qq_37729620的博客
10-22 157
首先来解释一下websocketwebsocket是全双工通信的协议,我们知道已有的http协议是一种只能由客户发起请求的协议,如果我们想要让服务器向客户主动发送信息或者实时数据更新,用http协议的话比较麻烦。简略介绍一下用http协议实现 第一种:轮询,顾名思义在客户设置一个固定时间间隔,比如每过五秒向服务器发送一次请求,不管数据有没有变化,服务器接收到请求后立刻处理...
Spring WebSocket 应用,鉴权token,多个页面访问同一个websocket
weixin_39263573的博客
08-10 6711
Spring WebSocket 应用,鉴权token 解决了1:建立连接成功后立即被关闭; 2:一个用户token下 多个页面访问同一个websocket不成功的
websocket实现通讯——Java
m0_65545927的博客
02-28 3522
websocket实现通讯——Java
springboot+websocket实现即时通信
08-11
Spring Boot是一种Java开发框架,而WebSocket是一种Web技术,通过结合使用这两者可以实现即时通信。 Spring Boot提供了对WebSocket的支持,可以很容易地实现一个WebSocket服务器。通过使用Spring的WebSocket模块,...

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 火爆全网的人工智能聊天机器人使用教程 24528
  • idea中各种for循环的快捷键 18625
  • Navicat最新永久使用安装方法 13601
  • 事务,提交,回滚 6920
  • Beyond Compare使用和安装教程 5019

分类专栏

  • 开源 46篇
  • Vue 1篇
  • 爬虫 1篇
  • SpringCloud 2篇
  • Eureka 1篇
  • idea 3篇
  • java 32篇
  • 事务 3篇
  • jdbc 2篇
  • java复制文件夹 1篇
  • 文件加密 1篇
  • 大数据 3篇
  • map 1篇
  • reduce 1篇
  • mapreduce 1篇
  • zookeeper 1篇
  • zookeeper配置 1篇
  • zookeeper入门 1篇
  • Java面试 2篇
  • java线程池 1篇
  • http协议 2篇
  • mybatis 1篇
  • Springmvc 1篇
  • spring 1篇
  • vm 1篇
  • java锁 1篇
  • 数据库优化 1篇
  • 数据库 3篇
  • 代理服务器 1篇
  • mysql5.5 1篇
  • Spark 1篇

最新评论

  • Beyond Compare使用和安装教程

    Sunder.Fang: 不用安装吗?

  • IDEA安装教程2023

    Symbol. Tao: 文末并没看到安装包

  • Beyond Compare使用和安装教程

    顾白白baibai: 没有安装向导啊

  • Visual Studio 2022 v17.6 正式发布

    数九天有一个秘密: 我还是喜欢2019。

  • 常见的一些内网穿透工具

    CSDN-Ada助手: 恭喜你,获得了 2023 博客之星评选的入围资格,请看这个帖子 (https://bbs.csdn.net/topics/615447851?utmsource=blogger_star_comment)。 请在这里提供反馈: https://blogdev.blog.csdn.net/article/details/129986459?utmsource=blogger_star_comment。

最新文章

  • PyCharm安装合集
  • Xshell安装使用教程
  • 最新整理的Pycharm安装教程
2024年8篇
2023年142篇
2019年10篇
2018年13篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员万万

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

深圳SEO优化公司临夏网站改版价格贺州优秀网站设计塔城关键词按天扣费推荐河源seo网站推广多少钱贵阳模板推广哪家好德州网站排名优化哪家好张家口模板网站建设云浮网站设计公司南通网站改版价格沈阳阿里店铺运营公司宿迁网站开发价格林芝网站优化按天计费推荐蚌埠至尊标王公司南平建站价格鹤壁seo网站优化价格福田网络广告推广推荐白银网站推广系统哪家好海口至尊标王价格大连百度标王泰州百姓网标王推广推荐辽源网站推广价格肇庆企业网站设计价格河源网站优化软件价格泉州网站优化软件多少钱湘西网站改版报价宿迁网站推广方案报价商洛企业网站设计天津设计网站价格曲靖百度seo推荐本溪网站开发歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化