网络编程

interview

1、http协议跟socket有什么区别?

  • http协议是一种无状态的协议:就是每次发出请求第一步都是客户端与服务端建立连接,连接成功之后把数据传过去,服务器收到数据进行响应,然后再回传结果给客户端,这一次请求结束之后连接就断开了,下次再发新的请求就会再重新建立连接

  • 而 socket 协议则不一样:socket协议意思就是长连接,言外之意就是发数据之后,连接不会断开,会一直保持连接

  • http是基于 udp协议的;socket是基于 tcp/IP 协议的

  • 相应的优缺点就很明显了:因为http每发送请求,就会断开连接,假设有1w个用户,如果用http协议,可能同时连接服务器的只有1000个用户,因为其他用户请求完就断开连接了;如果用socket可能同时会有1w个人连接服务器,这个就比较浪费服务器资源,消耗带宽。但是socket的优势也很明显,因为一直保持连接么,每次用户发送数据都很快,不用重新建立连接的过程,而http则每次都要重新建立连接,导致效率上没有socket高效

  • 应用:由于http协议每次都要重新建立连接,导致效率上没有socket高效;socket协议大多用IM,IM就是即时聊天应用,类似qq。微信

2、http协议一般包含两大块

  • 请求和响应,即request和response

    • request就是你在浏览器里输入一个网址,后者手机端发送一个网络请求都算 request
    • request 一般包含请求的 地址、参数、header、method

      • 地址:如www.baidu.com
      • 参数:参数包含两块,

        • 一种是 GET 请求
          http://www.baidu.com/?key1=value&key2=value2,像上述的 key1, key2 是参数的一种,这种叫做 query params,一般来说一个url 问号后面的都是参数

          • 还有一种就是 POST 请求
            最初网页上填写表单,比如填用户名、密码然后提交给服务器的;这种参数不会直接显示的,他通过body的方式传递给服务端;这种参数有的叫form即表单,也有的叫 body params,默认情况下都是一种 key 、value 对的形式传递的

            http的请求方法包含 get、post、delete、put、head、patch、trace、options,只不过我们常见的只有2中,即 get和post,而其他六种都是基于post方法衍生的;除了这两种,你们还需要了解 put delete这两种,总共加起来就是 get post put delete 四种最重要

            而这也是 restful 最基本的概念

    • 举个例子

      假设我们有如下需求:查询学生数量,创建新学生,修改学生信息,删除学生;get  /api/student/index  查询接口;post  /api/student/   携带一些 params 是创建接口;post  /api/student/update  携带一些参数   修改接;post  /api/student/update  携带一些参数   修改接口;
      
      可以看到只用了  get 和 post 方法,然后 api 的 url 定义的不太一样,但是如果用了 restful 方法 就会变成如下这样;get  /api/student/index  查询接口   不变;post  /api/student/   携带一些 params 是创建接口  不变;put  /api/student/ 携带一些参数   修改接口;delete  /api/student/携带参数  删除接口;
      
    • 以上的区别:

      修改跟删除直接用 http 的 method 来指定,url 哪怕一样,就可以轻松知道你的动作;这就是所谓的 restful 概念最重要的一个理念。
      
      • restful
        一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。—- 百度百科

      • header

        header 不管是request 还是 response 都有的一个东西;header的作用有很多,比如客户端告诉服务端 我发起的请求是什么语言;我发起的请求带的参数是什么格式的,是json还是哈希;我发起的请求需不需要带缓存;我发起的请求需要压缩等。这些信息都是通过header 传递的;服务端在返回结果的时候也有一些信息告诉客户端的,同样在header里传递,比如我返回的数据是什么格式的;我这次请求是不支持缓存的;我这次返回的数据没有压缩等。header里的信息都是一个个的哈希,即key value对;比如大家常见的一些 header里的信息 Content-Type: application/json,Cache-Control : true 等;header里默认的有很多字段,这是规定,当然你也可以自定义一些字段在里面传递,只要跟你们服务端约定好就行
        
        - 这里有个字段叫做  Connection: keep-alive,这个字段是什么意思呢?
        就是像http能不能实现socket一样的,http如果每次都请求断开未免太没效率了,后来有人就发现 :一般我在发起一个请求之后,可能紧接着就发起第二个请求了。如果频繁的断开重连效率太低了,于是就有了这个字段。这个字段顾名思义,就是声明连接的类型;这个字段有两个值,close 和 keep-live;如果你指定close,那么每次请求就会立马断开连接;如果你指明了 keep-live,就可以在一段时间内保持长连接,这个时间服务端可以自行配置,但是时间也不会太长,不然服务器会很吃紧,比如设置个30s,意味着这30s的时间内不会重新断开重连;
        
    • response,意为服务端返回的值

      服务端的返回刚刚说了有 header, response也会有header
      对于app中,目前大部分的response都是json格式的数据
      Android中有各种各样的json数据解析器,如gson、jackson、FastJson等等
      除了 返回的数据之外还有一个比较重要的叫做状态码(叫做 http  status),一般是 200—500,比如正常的时候返回的 status 就是200,代表成功;大家常见的status code有 404 找不到;500 代表服务器挂了;
      
      常见的几个状态码如 200表示链接成功,304表示缓存内容,404表示找不到 50x服务器挂了,其他很多状态码不常见
      
      • 记法:
        一般是 200开头的大多是成功;30x代表重定向,304是服务端告诉你内容没有改变,意为缓存的内容;40x一般是请求找不到,大部分是你url写错了;50x那就是服务器挂了
      • 整个http 最主要的就是 request 和 reponse。不要只会用一些网络库发送请求,接受结果就行了,却连最基本的http知识都不了解。

3、 http 的缓存

缓存是跟开发中最常见的一环,可以算是性能优化的一个大点了,缓存有两部分,客户端和服务端,做客户端的会以为缓存只有客户端才有,其实服务端更有;因为加上你没查一个数据,服务端都要到数据库重新查询一遍,那服务器压力得有多大,所以服务器会有一个缓存机制

  • 缓存有两种机制

    • 第一种最常见的就是时间缓存
      比如我查询中国的城市信息,中国的城市信息可能很久都不会变更,对于这部分假设我就设置7天的缓存时间,意味着客户端每次请求,服务端一次查询数据库,7天之内都不会再查询数据库,直接返回给你上一次的结果,对应的 status code 就是304,这对服务器性能优化是很大的一环

      缓存有没有生效一般用 header里的 cache-control 字段控制;如果客户端传递 cache-control 字段为 true 那么服务端有缓存的话就会启动缓存;如果传递 false 那么会强制服务端每次都去数据库里查询,一般不会这么干的;

      缓存的时间有一个字段叫做 expired 字段,告诉你缓存过期的时间

      一般来说,如果性能优化的话会有这么一个点,客户端发起一个请求,服务端返回数据,并且告诉客户端我这个请求有缓存的,缓存时间是7天,那么客户端就可以把这个请求结果缓存在本地,然后7天之内都不再发起请求,直接读取本地的缓存数据,那么会极大的节省服务器资源

    • 第二种就是Etag 缓存
      以时间为缓存的大多为那些请求数据不常变化的,但大多数场景是数据经常变化,比如我刷个微博,微博变化很快。可能1小时不会变化,但也可能1分钟就有更新,这种缓存就没法用固定的时间来进行衡量了,所以第二种缓存叫做 Etag 缓存

      Etag 你们可以理解成就是一个唯一的字符串,这个字符串是服务端根据时间、用户标识、内容索引等生成的一个字符串,一旦用户的内容变化,这个Etag就会变化,如果用户内容不变化,那么Etag也不会变化

      所以刷微博的话机制就是这样的,客户端发起一个请求,服务端返回了一个数据,告诉客户端,我是有缓存的,缓存的 Etag 值也返回给你了,然后我把返回的数据以及 Etag 缓存到本地,这样下次请求的话如果数据没有变化,那么服务端不会返回给你数据了,而只会返回一个 Etag值,拿到这个Etag值之后到本地去找这个Etag缓存对应的数据

      etag的生成与比较都是在服务端做的

      etag的缓存其实才是目前使用最多的缓存策略

      主流网络库都会默认支持这两种缓存,也就说volley或者okhttp都会支持的,以volley为例,他内部实现了缓存机制,每次请求之后如果服务端支持缓存的话,他自己只直接在本地进行缓存的,也就是说 如果服务端返回了 304 ,并返回了etag,volley会自动去本地寻找上次缓存过的数据进行渲染。

小额支持我写出更好的文章~