[面试] 4. 网络协议相关

本文章收录于:后端工程师面试题目总结(提供参考答案)

目录

1. GET和POST区别是什么,HTTP状态码了解哪些?

2.  Session和Cookie的区别?Session如何管理?

3. HTTPS的解释?为什么要有HTTPS?

4. 简述HTTPS密钥协商过程?

5. 简述跨域产生背景以及常见解决方案?

6. 解释一下socket长连接?和Websocket协议的区别?

7. 谈谈select和poll和epoll

8.  TCP与UDP区别;简述三次握手和四次挥手过程

9. TIME_WAIT过多的原因?如何解决?

10. CLOSE_WAIT什么时候出现?什么场景出现大量CLOSE_WAIT?如何解决?

11. 一个http请求由哪几部分组成?

12. 谈谈HTTP长连接和短连接

13. HTTP长连接与TCP长连接的关系


1. GET和POST区别是什么,HTTP状态码了解哪些?


    相同:两者都是HTTP请求,都是基于TCP协议工作的。
    区别:
    1.1 GET请求一般会被浏览器主动cache,POST不会
        (这点很重要,cache刷新页面浏览器不会再请求服务器,如果设置了max-age的话,减轻服务器负载,提升用户体验)
    1.2 GET请求中传送的参数是有长度限制的(协议规范没有,各个浏览器有,IE最短是2083bytes),
        POST没有(但受服务器处理能力影响)。程序内部调用则URL长度不受限制。
    1.3 GET参数是明文保存在URL中,POST参数保存在body中,URL可以在浏览器历史记录查看,而body不会被浏览器记录。


2.  Session和Cookie的区别?介绍几种会话管理方案?


    相同:两者都是用来跟踪浏览器用户身份的会话方式
    区别:

  •     2.1 cookie保存在客户端,session在服务器端
  •     2.2 保存在客户端就意味着cookie可能被分析并用来实施cookie欺骗,而session不会(也只是相对安全)
  •     2.3 session存在服务器端就意味着需要消耗服务器资源。
  •     2.4 cookie的大小会被浏览器限制,一般是4KB(包括key-value),session没有理论限制。

    小结:cookie和session两者各有优缺点,实际使用中可将两者结合。

  • 几种会话管理方案:

        第一种:保存在服务端,由服务端将所有用户的会话信息保存在内存中,然后返回一个唯一对应的sessionid给浏览器,浏览器将其保存在cookie中,下次请求发送cookie即可,如果服务器是集群部署或者分布式,可以用专门的缓存中间件来存储session。
        第二种:cookie-based,即将用户会话信息以cookie形式保存在浏览器,这种方式服务器无压力。只是cookie大小受制于浏览器。
        第三种:token-based,服务器将第一次登录传入的账户密码做了验证后,将时间戳+账户ID通过对称加密后得到的子串发给浏览器作为token,浏览器下次请求把明文账户ID和token放在header或者URL中带过来就行了,服务端解密token验证账户ID是否正确以及时间戳是否过期即可。


3. HTTPS的解释?为什么要有HTTPS?


    和HTTP一样也属于应用层,基于TCP协议,区别是:
    HTTP默认工作在80端口;后者是443端口
    HTTPS在HTTP基础上多了一个加密的身份验证层,即SSL。
    全称是:超文本传输安全协议。
    为什么要有HTTPS(主要作用):
        1. 建立一个信息安全通道,保证数据传输安全(HTTP是明文传输数据),被中间人截获的是加密内容。
        2. 确认网站真实性,使用HTTPS必须注册有效证书,证书包含注册人相关信息。

 

4. 简述HTTPS密钥协商过程?(参考文章

  •     4.1 客户端浏览器先将自己支持的一套加密规则发给网站服务器
  •     4.2 服务器从中选出一套加密算法与HASH算法,并加上证书发回给浏览器。     

        证书中包含网站地址、加密公钥、证书CA等信息。

  •     4.3 然后浏览器做以下验证:

        1. 验证CA是否合法,以及证书中的网站地址是否就是正在访问的地址,若都正常则再验证证书是否过期,
            若过期则页面会提示用户,用户自己选择是否信任该证书。
        2. 若证书有效或用户选择信任证书,浏览器会生成一串随机密码(这个很关键),并用公钥加密。
        3. 然后用之前约定好的HASH算法对握手消息进行HASH后得到一个hash值,
            再用随机密码对明文握手消息【对称加密】得到一个加密的握手消息。
        将上面生成的:
            a. 公钥加密过的随机密码
            b. 握手消息的hash值
            c. 握手消息的对称加密值
        发送给服务器。

  •     4.4 服务器收到一堆信息后做如下操作:

        1. 用自己的私钥解密取出随机密码
        2. 用随机密码解密握手消息
        3. 用协商好的hash算法对握手消息进行hash再匹配传过来的hash值是否一致
        4. 都OK,则用随机密码对称加密一个自己的握手消息和这个握手消息的hash值发给浏览器
        

  •     4.5 浏览器用随机密码提取握手消息,并计算hash值是否正确。

    * 至此密钥协商结束,随机密码就是后续的对称加解密的密钥。
    HTTPS一般使用的加密与HASH算法如下:
        非对称加密算法:RSA,DSA/DSS
        对称加密算法:AES,RC4,3DES
        HASH算法:MD5,SHA1,SHA256
        
    小结:HTTPS的通信过程分两阶段:密钥协商阶段+数据传输阶段,前者使用非对称加密,后者使用对称加密。
            每个客户端协商的密钥不同,服务器将维护多个密钥
    为什么后面要用相比不太安全的的对称加密?
    答:因为相较于非对称,对称加密不需要过多数学计算,更快更高效。

备注:证书申请之后,自己会有两个证书相关文件,一个是包含证书公钥、绑定域名、CA相关信息的文件,另一个是证书私钥,用来在HTTPS秘钥协商过程中使用的,证书文件的后缀可以是pem/cer/crt等,私钥文件后缀一般是pem,可参考此链接下文部分说明。

扩展:SSL证书申请过程

5. 简述跨域产生背景以及常见解决方案?

 

  •     5.1 产生背景

        实际开发工作中经常会有跨域的情况发生,比如
        1. 一个公司一般都有多个项目,自然也会有多个子域名,项目之间会有相互调用对方的功能/资源的需求,
            可以节省许多不必要的开发工作。
        2. 现在需要项目都是前后端分离,前端调用后端资源就是跨域请求。

  •     5.2 解决方案

        a. CORS(跨域资源共享)
            1. 需要浏览器支持,不过现在的浏览器几乎都支持。
            2. 这种方案会使得浏览器多出一次附加的预检请求(针对非简单请求)
            一般在反向代理服务器(如nginx)中进行配置,之后就不用再app中配置。
            在nginx的enable-cors.conf文件进行header配置,可以指定允许的跨域源URL。然后在nginx.conf 
            中include [enable-cors.conf]这个文件。
            扩展:服务器返回的“Access-Control-Max-Age” 是什么作用?
                答:用来指定本次预检的有效期,单位秒。有效期内同一个URL无需再发预检请求。
        b. jsonp跨域(仅支持GET方式)


        
6. 解释一下socket长连接?和Websocket协议的区别?


   Socket长连接其实指的就是TCP长连接的(UDP没有连接)
    指的是一个TCP连接上可以连续发送多个数据报,在连接空闲时,通过心跳包(keep-alive)维持,两端都有超时机制。
    优势:降低资源消耗,提高数据传输速率。(连接的建立和销毁比较浪费时间和资源)
    使用场景:访问量(连接数)较少,通讯频繁的情况,如聊天室、数据库连接。
    和Websocket协议的区别?
    socket长连接是允许一个TCP连接存活更久,更靠近底层,但消息边界(字节流解析)需要自己处理,而且是单工的,即客户方是固定的。
    websocket则是一种全新的协议,它基于http协议建立一个长久的连接,不需要处理消息边界问题,而且是一个全双工的模式;
    不需要心跳来维持,但是实际情况中可能会因为网络质量差或nginx访问超时设置等原因导致连接断开,所以一般都会
    在客户端设置心跳机制(30s一次),客户端实现心跳断开自动重连策略。


    
7. 谈谈select和poll和epoll


    select:时间复杂度是O(n)
            是对所有scoket句柄(fd)进行定时轮询,发现有准备就绪的fd,就对其操作。
            fd越多,轮询时间越长,当有准备就绪的fd是排在最后时,效率很低。
            
    poll:时间复杂度是O(n)
            本质上和select无差别,都是轮询机制,只是它没有最大fd数量限制。
    epoll:时间复杂度是O(1)
            这是一种事件驱动的机制,epoll能直接知道哪个fd状态变化,然后直接调用对应回调函数。
            这是一种非常高效率的机制,fd数量增加也不会影响其效率,上面两种会直接受到影响。

 

8.  TCP与UDP区别;简述三次握手和四次挥手过程


    相同:传输层协议,用于报文传输
    不同:TCP比UDP可靠,是面向连接的,拥有三次握手和四次挥手、以及流量管理、拥塞控制等机制来保证传输过程可靠,安全。
          而UDP传输过程简单,快速高效,且开销小,因为没有建立连接的过程,报文头部仅8字节,TCP头部20字节以及40字节可选项。
          但是它没有ACK和序列号机制,无法解决报文丢失和顺序错乱问题。
          
          TCP只能点对点(P2P),UDP可以一对一,一对多,多对多(P2MP)。
    

  •     三次握手:

        1. client发送SYN(seq=x)报文 => server(client状态变为SYN_SENT)
        2. server发送ACK(seq=x+1)以及SYN(seq=y)报文 =>client (server状态变为SYN_RECV)
        3. client发送ACK(seq=y+1) => server (client变为ESTABLISHED,服务器收到后也变为ESTABLISHED)   

  •     四次挥手:

        1. client发送FIN(seq=x) =>server (client变为FIN_WAIT_1)
        2. server先回复ACK(seq=x+1) => client (server只要收到FIN报文就会变为CLOSE_WAIT, client变为FIN_WAIT_2)
        3. server发送完剩余的数据报文后,再发送FIN(seq=y) =>client (server变为LAST_CHECK)
        4. client发送ACK(seq=y+1) => server (client变为TIME_WAIT)
        server收到ACK后直接就关闭closed状态,但client要等2MSL(最大报文生存时间)才会变为closed。
        client的状态转变顺序:established-->fin_wait_1->fin_wait_2->time_wait->closed
        server的状态转变顺序: established-->close_wait->last_ack->closed 

 

9. TIME_WAIT过多的原因?如何解决?

注意:TIME_WAIT只出现在“客户端”,这个“客户端”指的是先发FIN报文的一方。那么这里出现过多的TIME_WAIT的一方肯定不是我们常见的那个客户端,而是后台服务器,后台主动断开连接,那么它自然就成了所谓的“客户端”。
    这种情况一般出现在服务器短时间内处理了大量TCP请求,主动关闭连接时就会有这个状态,这个状态将持续可能1-4分钟。
    在这些连接状态变为CLOSED前其占用的socket资源都不能再使用,即无法建立新的连接。
    修改内核配置/etc/sysctl.conf:
    net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,
                                可防范少量SYN攻击,默认为0,表示关闭;
    net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
    net.ipv4.tcp_fin_timeout 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
    net.ipv4.tcp_max_tw_buckets = 10000 表示系统同时保持TIME_WAIT套接字的最大数量
    使之生效: /sbin/sysctl -p 

 

10. CLOSE_WAIT什么时候出现?什么场景出现大量CLOSE_WAIT?如何解决?


    CLOSE_WAIT是被动关闭方收到FIN报文后的状态,然后等待自身数据传输完成后,就会变为LAST_ACK状态。
    什么场景出现大量CLOSE_WAIT:
        主动关闭方发送了FIN报文,但被动关闭方收到之后没有响应(一般是因为上层服务没有及时调用socket的close方法,
        根本原因可能是程序死锁导致的耗时过久),主动关闭方会在自己设置的tcp连接超时时间结束后关闭socket,而被动关闭方则一直保持CLOSE_WAIT,直至超时。(默认CLOSE_WAIT会保持2小时)
    解决:检查服务端(出现CLOSE_WAIT)的机器本身对应进程的问题。
        如果程序本身没有问题,则修改内核参数:
        net.ipv4.tcp_keepalive_time = 1800  TCP连接的超时时间,默认7200s,适当减小这个值
        net.ipv4.tcp_keepalive_probes = 3   超时后探测包发送的次数,达到上面这个时间后以及探测包发送次数上限后,断开连接。
        net.ipv4.tcp_keepalive_intvl = 15   超时后探测包发送的时间间隔


        
11. 一个http请求由哪几部分组成?


    由请求方法、请求头、空行、请求体组成。

 

12. 谈谈HTTP长连接和短连接


    短连接就是一个http请求完成后即断开TCP连接,下次来仍然需要建立连接。
    
    长连接是一个http请求完成后仍然保持TCP连接,同域名下依然可以用这个通道传输数据。
    HTTP1.1 默认保持长连接,HTTP1.0就需要设置 Connection: Keep-alive。

    设置Connection: close 则不使用长连接。
    通过Keep-Alive : timeout-20(或max=20) 查看长连接最大空闲时间/单个长连接最大请求次数。
    当然服务端有可能不会告诉客户端连接保持时间,这不影响什么,服务端最后会用四次挥手来关闭连接,客户端
    会知道该连接不可用然后重新建立连接。
    
    长连接通过两种方式来识别单次传输结束:
        1. 通过Content-Length字段
        2. 若数据是动态生成,没有Content-Length,那就是分块传输(chunked),通过header中的Transfer-Encoding:chunk设置, 这时候通过最后一个长度为0的chunk来判断该次传输结束。

 

13. HTTP长连接与TCP长连接的关系


    前者处于应用层协议机制,后者是传输层机制,前者实现基于后者。
    HTTP中的keep-alive是http请求的header字段connection中应用,表示客户端希望服务器持久化本次TCP连接通道,在HTTP/1.1版本中浏览器默认开启,保持时间可以在客户端和服务端设置;
    TCP中的keep-alive是TCP协议的长连接机制,通过配置keep-alive超时时间来设置TCP连接的最大空闲时间,
    TCP连接空闲超时后,未关闭的socket会定时发送探测包来检测通道是否正常,若发送N次都未收到回应,则认为对方已关闭,然后关闭自己的socket。
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值