HTTP知识

屏幕快照 2018-07-15 上午3.55.54.png

输入域名到显示网页的网络过程



5层网络模型介绍

屏幕快照 2018-07-12 上午3.25.44.png

低三层

物理层主要作用是定义物理设备如何传输数据
数据链路层在通信的实体间建立数据链路连接
网络层为数据在结点之间传输创建逻辑链路

传输层:

两个协议 TCPIP 和 UDP ,向用户提供可靠的端到端(End-to-End)服务。
建立起了自己电脑到百度服务器(举例)的链接,它们两端如何去传输数据,它的传输数据的方式 ,都是在这层定义。
传输层向高层屏蔽了下层数据通信的细节

应用层:

为应用软件提供了服务 http / ftp 是构建于TCP 协议之上,屏蔽网络传输相关细节。



HTTP协议的发展历史

1、弄清楚一个概念,HTTP请求与TCP请求不是一个概念,在同一个TCP请求可以发送多个HTTP请求,以前的协议版本不能这么做,但是现在HTTP1.1.1里面可以这么做,而且在HTTP2里面是会更大的去优化相关的一些东西,来提高HTTP传输效率以及服务器的性能。

2、TCP连接对应多个HTTP请求,而一个HTTP请求肯定在某一个TCP连接里面去定义发送的。

5b0e4e340001703f19201080.jpg

第一个版本 HTTP / 0.9

只有一个命令 GET
没有HEADER 等描述数据的信息
服务器发送完毕就关闭

第二个版本 HTTP / 1.0

增加了很多命令
增加了status code 和 header
多字符集支持、多部分发送、权限、缓存 等等

第三个版本 HTTP / 1.1

持久链接
pipleine
增加了 host 和其他一些命令 (在同一个物理服务器可以同时跑很多服务)
第四个版本 HTTP / 2.0

所以数据都是以二进制传输
同一个链接里面发送多个请求不在需要按照顺序来
头信息压缩以及推送等提高效率的功能

HTTP2

1、所有数据以二进制传输
同一个连接里面发送多个请求不再需要按照顺序来(可以同时返回数据)
头信息压缩以及推送等提高效率的功能:
头信息压缩:在HTTP1发送和返回请求,http头都是必须完整发送并返回,带宽量大。
2、推送:http请求只能是发送然后响应返回内容,客户端永远是主动方,服务端是被动方。http2有了推送,服务端可以主动发起数据传输。
如:web页面里面有css,img,js等文件,它们都是连接的形式,这里就有顺序的问题,解析文本之后才能发送对应的链接请求,http2有了推送功能,在请求的同时,可以主动把这个页面的css,img,js等文件推送到客户端,这样发送顺序是并行的,不是串行的,性能高出许多。

HTTPS

安全版本的HTTP。



HTTP的三次握手

5b1f8d2a0001d56119201080.jpg

在客户端和服务器端之间进行http请求的发送和返回的过程当中,需要创建TCP connection,因为http不存在连接这样的概念,它只有请求和响应,里面都是数据包,需要经过传输的通道,这个通道就在TCP里面创建了从客户端发起到客户端接收的这样的一个连接,这个连接可以一直保持,http请求就是在这个连接的基础上发送的。

在TCP上面可以发送多个http请求,在不同http版本里,这个模式是不一样的。

http1.0:TCP连接是在一个http请求创建的时候,就去创建这个TCP链接,链接创建完了之后,请求发送过去,服务器响应了之后,这个TCP连接就关闭了。

http1.1:TCP链接可以通过某种方式去声明链接一直保持,就是在第一个请求发送之后,TCP链接没有关闭,第二个请求来了之后,还可以在这个没有关闭的链接上进行发送。

http2:的TCP链接上面的http请求时可以并发的,如果同一个用户对同一个服务器发起一个网页请求的时候,只需要一个TCP连接。

长链接好处

  • TCP链接在创建的过程中要经历三次握手这么一个消耗,代表着有三次网络传输:客户端发送-服务端返回-客户端再发送-创建TCP链接,这个时候才可以发送HTTP请求,所以如果我们把TCP链接保持,那么第二个http请求就没有三次握手的开销。

TCP三次握手

屏幕快照 2018-07-12 上午4.19.46.png
TCP握手过程

1.客户端发起一个我要连接的数据包请求给服务器,里面会有一个SYN的标志位,标志这是一个创建请求的数据包

2.服务端接收到数据包后知道有一个客户要和它建立链接了,然后会开启一个TCP socket 端口,开启之后返回数据给客户端,数据包含 SYN标志位,ACK= X+1,Seq=Y

3.客户端拿到数据包后意味着服务器端允许创建TCP连接,然后发送数据包 ACK = Y+1,Seq=Z

为什么要三次握手创建TCP连接?

为了防止服务端开始无用的链接,网络传输是有延时的,传输过程中防止丢包,造成重复创建链接,资源浪费,所以设置三次握手。为了规避网络传输延时。
三次握手确认客户端发起到服务器返回的过程,就是为了规避这些在网络传输过程中延时导致的一些服务器开销的问题。



URI-URL和URN

user:pass@ 代表访问资源的身份使用用户名和密码

host.com 用来定位资源的服务器在互联网中的位置(可以是IP 也可以是 域名)

:80 端口,每台物理服务器可以跑很多软件的web服务,端口就是监听物理服务器上面某个具体的web服务

/path 路由,web 服务器里面的内容可以通过路由进行定位

?query=string 搜索参数

hash 查找文档的某个片段


5b41e95600010d8319201080.jpg


HTTP报文格式

屏幕快照 2018-07-12 上午5.13.34.png

method :

GET:获取数据
POST:创建数据
PUT:更新数据
DELETE : 删除数据

http方法:用来定义对于资源的操作

http code :定义服务器对请求的处理结果

100-199代表操作要持续进行
200-299代表成功
300-399需要重定向
400-499代表请求有问题
500-599服务器错误



CORS跨域请求的限制与解决

请求已经发送了,内容也已经返回了,只不过浏览器在解析了内容之后,发现这是不允许的,所以帮你拦截了,这其实是浏览器提供的功能。

跨域 : 在这个网页发送一个请求,如ajax请求,都必须在同域的,如果跨域,需要服务器同意,才能够接收到返回内容。

jsonp到底做了什么?
建立script标签,src放置请求地址,即可。因为浏览器允许link,img,script标签上的路径加载内容,并不在乎服务器是否设置了跨域的头,jsonp的原理其实就是在script上加载了一个连接,这个连接去访问了服务器的某一个请求并返回内容。

设置请求头

 response.writeHead(200,{
        'Access-Control-Allow-Origin':'*'
    })

'Access-Control-Allow-Origin'的值:
'Access-Control-Allow-Origin':'*

  • '*' : 任何服务,任何域名都可以访问服务器。的做法 :
    更安全'Access-Control-Allow-Origin':'http://baidu.com',只允许指定的域名请求。


缓存头Cache-Control的含义和使用

自定义的头在跨域请求时不被允许的

        fetch('http://localhost:8887/',{
            method:'POST',
            headers:{
                // 自定义头
                'X-Test-Cors':'123'
            }
        })

自定义的头在跨域请求时不被允许的

CORS预请求限制

跨域时默认允许的方法(不需要预请求)

  • GET
  • HEAD
  • POST
    除了以上三种,都会先发送预请求
    允许Content-Type
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlendoded

其他限制

  • 请求头限制
  • XMLHttpRequestUpload对象均没有注册任何事件监听器
  • 请求中没有使用ReadableStream对象

什么是预请求

浏览器根据Response Headers判断请求是否允许


31ABEC72-7A20-4D65-AAE0-E51B99278EF9.png

解决:设置允许访问的自定义请求头

http.createServer(function(request,response){
    console.log('request come',request.url)
    response.writeHead(200,{
        'Access-Control-Allow-Origin':'*',
        // 设置允许访问的自定义请求头
        'Access-Control-Allow-Headers':'X-Test-Cor'

    })
    response.end('123')
}).listen(8887)

浏览器跨域请求之预请求操作:Request Method:OPTIONS,首先发送这个请求,服务端可以根据不同的method进行不同的操作,允许接下来实际发送的请求。通过这个OPTION来获得服务端允许的任何请求,然后再实际发送设置的请求。
做跨域文件上传的时候,浏览器会自动发起一个 OPTIONS 方法到服务器。普通的 ajax 请求,也不会发起这个请求,只有当 ajax 请求绑定了 upload 的事件并且跨域的时候,就会自动发起这个请求。用于探测后续真正需要发起的跨域 POST 请求对于服务器来说是否是安全可接受的,因为跨域提交数据对于服务器来说可能存在很大的安全问题。

概括:允许跨域的请求 : get , post,options
发送的请求跨域了,浏览器会自动发送一个options预请求,询问后端支持的跨域请求方法。后端需要设置允许请求的方法。

router.options('/upload', function* (){
    this.set('Access-Control-Allow-Method', 'POST');
    this.set('Access-Control-Allow-Origin', 'http://xxx.com');
    this.status = 204;
});

204 :告知客户端表示该响应成功了,但是该响应并没有返回任何响应体,options预响应。如果状态码为 200,还得携带多余的响应体,在这种场景下是完全多余的,只会浪费流量。


浏览器为什么设置请求限制?
因为浏览器希望在网页进行跨域请求操作的时候是保证服务端的安全的,不允许任何随便进行跨域,不允许随便的方法进行跨域,以防数据被恶意篡改。所以提供这些限制之后,就可以进行一些非常有利的判断。

http.createServer(function(request,response){
    console.log('request come',request.url)
    response.writeHead(200,{
        // 设置允许跨域的访问地址
        'Access-Control-Allow-Origin':'*',
        // 设置允许访问的自定义请求头
        'Access-Control-Allow-Headers':'X-Test-Cors',
        // 设置允许跨域的methods
        'Access-Control-Allow-Methods':'POST,Put,Delete',
        // 允许以上三个方式进行跨域的最长时间,1000秒内不需要发送预请求验证了
        'Access-Control-Max-Age':'1000'
    })
    response.end('123')
}).listen(8887)



Redirect

通过url去访问一个路径的时候,这个资源可能已经不在这个url指定的位置了,服务器要告诉浏览器这个资源具体的位置,然后浏览器再去重新请求这个指定的位置。所以如果资源换了位置,不应该马上废弃url,应该告知客户端资源正确的位置。



CORS跨域限制以及预请求验证

自定义的头在跨域请求时不被允许的

        fetch('http://localhost:8887/',{
            method:'POST',
            headers:{
                // 自定义头
                'X-Test-Cors':'123'
            }
        })

自定义的头在跨域请求时不被允许的

CORS预请求限制

跨域时默认允许的方法

  • GET
  • HEAD
  • POST

允许Content-Type

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlendoded

其他限制

  • 请求头限制
  • XMLHttpRequestUpload对象均没有注册任何事件监听器
  • 请求中没有使用ReadableStream对象

什么是预请求

浏览器根据Response Headers判断请求是否允许


31ABEC72-7A20-4D65-AAE0-E51B99278EF9.png

解决:设置允许访问的自定义请求头

http.createServer(function(request,response){
    console.log('request come',request.url)
    response.writeHead(200,{
        'Access-Control-Allow-Origin':'*',
        // 设置允许访问的自定义请求头
        'Access-Control-Allow-Headers':'X-Test-Cor'

    })
    response.end('123')
}).listen(8887)

浏览器跨域请求之预请求操作:Request Method:OPTIONS,首先发送这个请求,服务端可以根据不同的method进行不同的操作,允许接下来实际发送的请求。通过这个OPTION来获得服务端允许的任何请求,然后再实际发送设置的请求。


浏览器为什么设置请求限制?
因为浏览器希望在网页进行跨域请求操作的时候是保证服务端的安全的,不允许任何随便进行跨域,不允许随便的方法进行跨域,以防数据被恶意篡改。所以提供这些限制之后,就可以进行一些非常有利的判断。

http.createServer(function(request,response){
    console.log('request come',request.url)
    response.writeHead(200,{
        // 设置允许跨域的访问地址
        'Access-Control-Allow-Origin':'*',
        // 设置允许访问的自定义请求头
        'Access-Control-Allow-Headers':'X-Test-Cors',
        // 设置允许跨域的methods
        'Access-Control-Allow-Methods':'POST,Put,Delete',
        // 允许以上三个方式进行跨域的最长时间,1000秒内不需要发送预请求验证了
        'Access-Control-Max-Age':'1000'
    })
    response.end('123')
}).listen(8887)

缓存头Cache-Control的含义和使用

特性:

以下这些头只是限制性的,声明性的作用,没有强制约束力。只是为代理服务器设置了这些头,要求按照规范去做,但是完全可以不按照这个规范做。

可缓存性
  • public
    在http请求返回的过程当中,在Cache-Control设置了public值,代表这个http请求返回的内容所经过的任何路径当中,包括一些中间的http代理服务器以及我们发出请求的客户端浏览器,都可以进行对返回内容的缓存操作:就是把这份数据存在本地,下次直接读这个缓存,不需要到返回这个内容的服务器上面重新进行操作返回内容。可缓存性是指哪些地方可以执行这些缓存。
  • private
    只要发起请求的浏览器才可以缓存
  • no-cache
    任何节点都不可以缓存。可以在本地服务器缓存,每次发起请求都需要去服务器验证,如果服务器说可以使用缓存,才能使用缓存。也就是说需要经过服务器验证的。
到期
  • max-age=<seconds>
    缓存有效期
  • s-maxage=<seconds>
    代替上面的max-age,但是只有在代理服务器里面才会生效
  • max-stale=<seconds>
    max-stale:浏览器用不到,浏览器并不会主动去设置这个头,只有在发起端设置是有用的,服务端返回的内容中设置没有用。发起请求方,主动带的头,在max-age过期之后,如果我们返回的资源中有这个max-stale设置,还可以使用过期的缓存,而不需要去服务器请求新的内容。

重新验证

  • must-revalidate
    设置了max-age,如果缓存已经过期了,必须去原服务端发送这个请求,重新获取数据,来验证内容是否真的过期了,而不能直接使用本地缓存。
  • proxy-revalidate
    用在指定缓存服务器,在过期的时候必须去原服务器重新请求一遍,而不能直接使用本地缓存。

其他

  • no-store
    本地和代理服务器不可以存储这个缓存,永远要去服务器拿新的body的内容。
  • no-transform
    不允许代理服务器不要改动返回的内容

浏览器中用到的

可缓存性 :
  • public
  • private
  • no-cahe
到期
  • max-age=<seconds>
  • s-maxage=<seconds>
  • max-stale=<seconds>

重新验证

  • must-revalidate

  • 设置请求文件缓存时间
    'Cache-Control': 'max-age=20'
http.createServer(function (request, response) {
  console.log('request come', request.url)

  if (request.url === '/') {
    const html = fs.readFileSync('test.html', 'utf8')
    response.writeHead(200, {
      'Content-Type': 'text/html'
    })
    response.end(html)
  }
  
  if (request.url === '/script.js') {
    response.writeHead(200, {
      'Content-Type': 'text/javascript',
      // 设置到期时间
      'Cache-Control': 'max-age=20'
    })
    response.end('console.log("script loaded")')
  }
}).listen(8888)

问题 : 这时如果改变了服务器返回的结果,刷新,发现返回的还是之前的结果,并不是最新的。这是因为服务器端更新了之后,客户端还是请求的缓存的资源,这样想要更新一个应用的时候,客户端根本触及不到了,一般max-ag可能会设置一年。
解决:在构建流程的时候,把打包完成的JS文件名根据内容的hash结果,加上一串hash码,这串hash码是因为根据打包完成的js以及其他静态资源的文件内容进行性的hash计算,所以如果这些静态文件内容没有变,hash码就不变,反应到web页面上就是url没有变,那么就可以使用静态缓存;而如果你的内容有变,hash码就会变化,嵌入在html的url路径就有变化,有了变化之后发起的请求就是一个新的静态资源请求而不是之前缓存的请求。这样就可以达到缓存的目的。



缓存验证:Last-Modified和Etag的使用

资源验证

如果catche-Ctrol设置了no-cache(任何节点都不可以缓存。可以在本地服务器缓存,每次发起请求都需要去服务器验证,如果服务器说可以使用缓存,才能使用缓存。也就是说需要经过服务器验证的。)

设置了Catche-Ctrol的请求过程如下:

屏幕快照 2018-07-13 上午1.30.48.png

数据如何验证?

1、验证头
  • Last-Modified
    上次修改时间。给资源设置了上一次是什么时候被修改的。
    配合If-Modified-Since或者If-Unmodified-Since使用。
    验证是否可以使用缓存的过程:如果我们请求了一个资源,如果返回的head里面有以上两个头信息,指定了时间,下次在请求的时候就会带上这两个传过来的值到服务器,通常浏览器都是用If-Modified-Since,服务器就可以通过读取head里面的If-Modified-Since的值,然后对比资源存在的地方,对比上次修改时间,如果发现这两个时间是一样的,代表这个资源还没有被修改,服务器就告诉浏览器直接使用缓存。对比上次修改时间以验证资源是否需要更新
  • Etag
    一个更加严格的验证。
    • 数据签名
      一个资源对它的内容会产生一个唯一的签名,如果这个资源进行了修改,这个签名就会变成新的,这样前后的签名就不一样。
      典型做法:对内容进行hash计算(就像打包文件一样,对内容计算就会得到一个唯一值)。用来标记这个资源。
    • 配合if-Match或者If-Non-Macth使用
      下次请求就会带上这两个值,就是服务端返回的Etag值。
    • 对比资源的签名判断是否使用缓存

if (request.url === '/script.js') {
    response.writeHead(200, {
      'Content-Type': 'text/javascript',
      // 设置到期时间 , 每次发起请求都需要去服务器验证
      'Cache-Control': 'max-age=20000000000,no-cache',
      //Last-Modified
      'Last-Modified' : '123',
      // Etag
      'Etag' : 777
    })
A8F61FED-5EA4-48F9-910A-CB265B35A309.png
4CD9A88D-EA45-4ACC-ADD9-9CE815E6DE6B.png

这个时候依旧返回了内容,因为内容并没有修改,所以不需要服务器返回response,做法如下:对比Etag

// 如果两次结果相同,返回缓存结果为空
     const etag = request.headers['if-none-match']
     if(etag === '777'){
         response.writeHead(304, {
             'Content-Type': 'text/javascript',
             'Cache-Control': 'max-age=20000000000,no-cache',
             'Last-Modified' : '123',
             'Etag' : 777
         })
         // 设置请求结果为空
         response.end('')
     }else{
         response.writeHead(200, {
             'Content-Type': 'text/javascript',
             'Cache-Control': 'max-age=20000000000,no-cache',
             'Last-Modified' : '123',
             'Etag' : 777
         })
         // 否则就是内容修改了,返回最新结果
         response.end('console.log("script loaded twice")')
     }
9C8E1CA3-F7E6-4358-8988-2146E60FC26E.png


cookie&&session

什么是cookie?

通过服务器返回数据后,通过:Set-Cookie设置保存在浏览器里的内容。浏览器在保存了这个内容之后,下一次在同域里的请求当中带上这个Cookie。这样就可以实现在这次访问网站的会话中,可以通过Cookie一直在传输的内容来保证我们返回的数据是这个用户的。


8189D6AA-FF8D-4BEB-9656-17FEC7F5F57C.png
屏幕快照 2018-07-13 上午3.31.02.png

屏幕快照 2018-07-13 上午3.33.10.png

cookie属性

  • max-age 和 expires 设置过期时间
  • Secure 只在https的时候发送
  • httpOnly无法通过js访问,浏览器中还是有的。
    安全性,比如csrs攻击,会通过在网页注入脚本,或通过url来引导用户去给攻击者的服务器发送用户自己的,这样他就能拿到这个这个cookie,从而访问我们网站中保存的用户的数据。禁止重要的数据通过JS访问,是保护用户数据安全重要的一步。

cookie时效

  • 如果没有设置时间,浏览器关闭失效。
  • 'Set-cookie': ['id=123; max-age=30', 'name=lin'] : id=123->
    30s后失效

设置test.com以及test.com的所有二级域名享受到cookie
5b2bb4300001195019201080-156-88.jpg


session:

Cookie保存session,经常做的就是把用户登录之后的ID,或者session的key设置到cookie里面。能够保证定位到用户,就是session实现的方案。



HTTP长连接

DDC479CE-5E35-4E71-B9E0-0678D155C19E.png

AA0E6755-3717-4D3A-9D9E-F54E11F89428.png

http请求时在TCP的连接上发送的,TCP的连接分为长链接和短连接。
长链接: HTTP请求在发送的时候,要先去创建一个TCP连接,然后在这个连接上把http请求发送并且接收完返回。这个时候,因为一次http请求已经结束了,浏览器和服务端就会商量,是否要把TCP连接关闭,如果不关闭,这个TCP连接会一直开着,一直消耗,但是如果下次再有请求,可以直接在TCP连接上发送,那么就不需要经过三次握手了。如果直接关闭,就意味着下次请求又要重新创建一个连接,这个时候就会有网络延迟的开销。
请求之后就关闭的好处 : 减少客户端和服务端高并发的连接数。实际中网站并发量会比较大,如果一直重新创建链接,会导致这个创建过程过多。



数据协商

客户端发送请求到服务端的时候,客户端会声明需要拿到的数据格式以及数据相关的限制,服务端会根据这些判断,可能会有不同类型的数据的返回。服务端会根据客户端发送过来的这些头信息来确定到底要返回什么样的数据。

分类

  • 请求
    Accept:声明想要的数据
    • Accept:指定数据类型
    • Accept-Encoding : 代表数据是以什么编码方式来进行传输,主要用来限制服务端如何进行数据压缩。
    • Accept-Language : 世界语言不通,不同地方期望展示的不同。
    • User-Agent : 判断返回的是PC还是M端页面
  • 返回
    Content
    • Content-Type
    • Content-Encoding
    • Content-Language


csp

xss : 通过某些方法在网站里注入一些脚本,导致页面出现问题,甚至窃取用户信息。很可能就是通过网站提供的富文本编辑器之类的工具,插入script内容。
限制方法:在服务器返回的头里面写入'Content-Security-Policy'。

  • 只能通过http: https加载,不能直接写在html
  • 如果通过外链加载的JS文件,指定域名可以加载,只能本域名下的JS文件可以加载
//限制default-src,只能通过http: https加载,不能直接写在html
'Content-Security-Policy':'default-src http: https'
屏幕快照 2018-07-13 下午4.41.24.png
如果在页面直接写了JS,报错

可以写在meta标签

  <meta http-equiv="Content-Security-Policy" content="script-src 'self'; form-action 'self';">



http明文传输:

互联网中的每一层,如果有人拦截,解析数据包并读取就可以获取相关信息。

https:

私钥:解密公钥加密过的内容,中间截取的人无法解密
公钥:放在互联网上,所有人都可以拿到的加密字符串

这样就是安全的过程。公钥和私钥主要是在握手过程中进行传输,加密字符串。客户端和服务端解密,中间人无法解密。
屏幕快照 2018-07-15 上午3.36.23.png

两者的主要区别就在于握手阶段。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 数据链路层使用的信道有以下两种类型: ①点对点信道,一对一的点对点通信方式 ②广播信道,一对多的广播通信方式,复杂...
    dmmy大印阅读 3,162评论 0 3
  • 数据链路层使用的信道主要有以下两种类型 点对点信道这种信道使用一对一的点对点通信方式 广播信道这种信道使用一对多的...
    srtianxia阅读 2,775评论 0 5
  • 13.服务器图片改了,url没有变,需求,服务器的图片变了,就从服务器加载图片,如果服务器的没变,就从本地加载 1...
    AlanGe阅读 1,134评论 0 1
  • 我的上周总结:自然醒的时间是5:40,已经没有使用闹钟,运动有跑步加跑前跑后拉伸3天,周六第一次突破了5公里,...
    妞尔多阅读 182评论 0 0
  • 记得去年有一次等公交车上班,过了好久公交都迟迟不来,我看了看表,时间要不赶趟了,而后打了车。 (我去年打车的那个司...
    烟花雨荨阅读 146评论 0 1