远程通信协议

一个Http请求的整个流程

负责域名解析的 DNS 服务

  • 用户访问域名,经过DNS解析,应用层协议,提供域名到IP的解析服务

    • 不用域名也可以访问目标主机的服务,但是IP本身不是那么容易记

加速静态内容访问速度的CDN

  • CDN (Content Delivery NetWork) 内容分发网络

    • CDN是一种网络缓存技术,把一些相对稳定的资源放到距离最终用户较近的地方

    • 一节省整个广域网的带宽销毁,二提升用户的访问速度

    • 静态文件放到CDN

HTTP协议通信

  • 域名被解析之后,客户端和服务端之间,这么建立连接,并且如何通信?

    • TCP和UDP通信协议,http协议是基于tcp/ip协议之上的应用层协议,还有FTP

    • OSI七层网络模型

      • 应用层

      • 表示层

      • 会话层

      • 传输层

      • 网络层

      • 数据链路层

      • 物理层

    • TCP/IP四层概念模型

      • 应用层

      • 传输层

      • 网络层

      • 数据链路层

    • 请求发起过程,在tcp/ip四层网络模型中所作的事情

      • 当应用程序用TCP传送数据时,数据被输入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部消息

        • www.xq.com 发送请求

          • 传输层 [[TCP头] [HTTP请求报文] ]

            • 表示当前的协议头,使用TCP协议传输

            • 相当于,针对这个包裹,选择了那个公司

          • 网络层 [[IP头] [TCP头] [HTTP请求报文] ]

            • 增加IP头,IP地址是一个网卡在网络中的通讯地址,相当于门牌号。

            • 这个包裹要寄送到那个地方

          • 数据链路层 [ [MAC头] [IP头] [TCP头] [HTTP请求报文] ]

            • 增加MAC头,表示这个数据包要发送到的网卡地址

            • 填写的包裹要寄送给哪个具体的人

          • 物理层 转为 01011 比特流进行传输

      • 客户端如何找到目标服务

        • 目标机器的mac地址怎么得到的?

          • ARP协议

            • 已知目标机器的IP,需要获得目标机器得MAC地址,发送一个广播消息,这个IP是谁得,请来认领。认领的IP机器会发送一个MAC地址的响应

          • 有了这个目标的MAC地址,数据包在链路层上广播,MAC的网卡才能发现,这个包是给它的。MAC的网卡把包收进来,然后打开IP包,发现IP地址也是自己的,再打开TCP包,发现端口也是自己的,也就是80端口,而这个时候这台机器有一个nginx是监听80端口

          • 于是,请求提交给nginx,nginx返回一个网页,需要发会请求到机器,然后层层封装,最后到MAC层,因为来的时候有源MAC地址,返回的时候,源MAC就变成了目标MAC,再返回给请求的机器

          • 为了避免每次都用 ARP 请求,机器本地也会进行 ARP 缓存。当然机器会不断地上线下线,

            IP 也可能会变,所以 ARP 的 MAC 地址缓存过一段时间就会过期。

      • 接受端收到数据包以后的处理过程

        • 当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由低向上升,同时去掉各层协议加上的报文首部

          • 服务器 接受请求

          • 传输层 [[TCP头] [HTTP请求报文] ]

            • TCP会携带端口,将报文交给指定端口的进程进行处理

          • 网络层 [[IP头] [TCP头] [HTTP请求报文] ]

            • 拿到IP头,判断IP地址是不是自己的,如果不是就转发,继续交给上面

          • 数据链路层 [ [MAC头] [IP头] [TCP头] [HTTP请求报文] ]

            • 拿到数据以后,从数据中摘到第二层的头,检查下MAC地址和当前网卡的MAC是否匹配,如果匹配说明发给我是没错的

          • 物理层 0101

            • 当数据通过网卡的时候,看看数据是否需要请进来坐坐

      • 为什么有了 MAC 层还要走 IP 层呢?

        • MAC地址是唯一的,MAC地址是身份证,但是跟个人所在的位置,没有关系,IP就类似于,城市+道路号+门牌号的概念

      • TCP/IP 的分层管理

        • TCP/IP 协议,分为四层,应用,传输,网络,数据链路层,提出了分层负载

          • 分层负载

            • 二层负载

              • 通过改写报文的目标 MAC 地址的方式将请求转发到目标机器实现负载均衡

            • 三层负载

              • 三层负载均衡会通过一个虚拟 IP 地址接收请求,然后再分配到真实的 IP 地址

            • 四层负载

              • 四层通过虚拟 IP + 端口接收请求,然后再分配到真实的服务器

            • 七层负载

              • 七层通过虚拟的 URL 或主机名接收请求,然后再分配到真实的服务器。

         

TCP/IP 协议的深入分析

通信协议的原理,到底客户端跟服务器端,是怎么产生关联的?

  • TCP握手协议

    • 三次握手,就是在建立TCP链接时,客户端与服务端总共发3个包来确定链接的建立

      第一次
      第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。  
      ​
      第二次
      第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。 
      ​
      第三次
      第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
      ​
      • CLosed CLOSED

        • Listen

      • SYN_SENT SYN_RECV

      • ESTABLISHED ESTABLISHED

      • ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。

      • SYN:同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号。

      • SYN_RECV:是指,服务端被动打开后,接收到了客户端的SYN并且发送了ACK时的状态。再进一步接收到客户端的ACK就进入ESTABLISHED状态。

  • SYN攻击

    • Client端在短时间内伪造大量不存在的IP地址,并向Server不断发送SYN包,Server回复确认包,进入SYN_RECV状态,由于源地址不存在,这些伪造的SYN包尝试占用未连接队列导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。

    • 措施

      • 针对SYN攻击的几个环节,提出相应的处理方法:
        ​
        方式1:减少SYN-ACK数据包的重发次数(默认是5次):
        ​
        sysctl -w net.ipv4.tcp_synack_retries=3 
        sysctl -w net.ipv4.tcp_syn_retries=3 
        方式2:使用SYN Cookie技术:
        ​
        sysctl -w net.ipv4.tcp_syncookies=1 
        方式3:增加backlog队列(默认是1024):
        ​
        sysctl -w net.ipv4.tcp_max_syn_backlog=2048 
        方式4:限制SYN并发数:
        ​
        iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT --limit 1/s
  • TCP四次挥手协议

    • TCP断开连接的时候,需要客户端和服务端总共发送4个包以确定连接的断开

      • 双方均可发起挥手动作因为TCP是一个全双工协议

        • 单工:广播 一个方向上传输

        • 半双工 :电报 某一个时刻,只允许在一个方向上传输

        • 全双工 :同时两个方向传输,它要求发送接受设备,都有独立的接受发送能力

    • 流程

      • 第一次挥手(FIN=1,seq=x)
        假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为 1 的包,表示自己已经没有数据
        可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。
        ​
        第二次挥手(ACK=1,ACKnum=x+1)
        服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,
        但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这
        个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。
        ​
        第三次挥手(FIN=1,seq=w)
        服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为 1。发送完毕后,服务器
        端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
        ​
        第四次挥手(ACK=1,ACKnum=w+1)
        客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待
        可能出现的要求重传的 ACK 包。
        服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
        ​
        客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)
        之后,没有收到服务器端的 ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接,
        进入 CLOSED 状态。
    • 问题

      • 为什么连接的时候是三次握手,关闭的时候却是四次握手?

        • 这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。
          ​
          但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你未必会马上会关闭SOCKET,也即可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
      • 为什么 TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSE

        状态?

        • 虽然按道理,四个报文都发送完毕,我们可以直接进入 CLOSE 状态了,但是我们必须假
          象网络是不可靠的,有可以最后一个 ACK 丢失。所以 TIME_WAIT 状态就是用来重发可能丢
          失的 ACK 报文。
      • 为什么不能用两次握手进行连接?

        •   3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
          ​
            现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
          ​
      • 如果已经建立了连接,但是客户端突然出现故障了怎么办?

        • TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
          ​

     

使用协议进行通信

tcp 连接建立以后,就可以基于这个连接通道来发送和接受消息

  • socket 是一种抽象层,应用程序通过它来发送和接收数据的

  • 可以把应用程序添加到网络中,并与处于同一个网络中的其他应 用程序进行通信

流程:

  • 应用程序

  • TCP套接字

  • TCP端口

  • IP

理解 TCP 的通信原理及 IO 阻塞

对于 TCP 通信来说,每个 TCP Socket 的内核中都有一个发送缓冲区和一个接收缓冲区,
TCP 的全双工的工作模式及 TCP 的滑动窗口就是依赖于这两个独立的 Buffer 和该 Buffer的填充状态。

发送端 接受端

send() recv()

TCP发送缓存区 TCP接受缓存区

TCP报文段 TCP报文端

应用层用户的Buffer -> 接受缓存区 -> 内核 -> 网卡

  • socket的read的工作就是把内核接受缓冲区中的数据复制到应用层用户的Buffer

  • send,则是将应用层用户的Buffer复制到 Socket 的内核发送缓冲区

  • 如果应用进程一直没有读取,那么 Buffer 满了以后

    • 通知对端 TCP 协议中的窗口关闭,保证 TCP 接收缓冲区不会移除,保证了 TCP 是可靠传输的

    • 如果对 方无视窗口大小发出了超过窗口大小的数据,那么接收方会把这些数据丢弃。

  • 滑动窗口协议

    • 滑动窗口(Sliding window)是一种流量控制技
      术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道
      网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动
      窗口机制来解决此问题;发送和接受方都会维护一个数据帧的序列,这个序列被称作窗口
    • 发送窗口

      • 就是发送端允许连续发送的幀的序号表。

        发送端可以不等待应答而连续发送的最大幀数称为发送窗口的尺寸。

    • 接受窗口

      • 接收方允许接收的幀的序号表,凡落在 接收窗口内的幀,接收方都必须处理,落在接收窗口

        外的幀被丢弃。

        接收方每次允许接收的幀数称为接收窗口的尺寸

理解阻塞到底是什么回事

accept 是一个阻塞的方法,意味着 TCP 服务器一次
只能处理一个客户端请求,当一个客户端向一个已经被其他客户端占用的服务器发送连接请
求时,虽然在连接建立后可以向服务端发送数据,但是在服务端处理完之前的请求之前,却不会对新的客户端做出响应

一个客户端对应一个线程

  • 弊端

    • 创建一个线程需要占用 CPU 的资 源和内存资源

    • 线程数增加,系统资源将会成为瓶颈最终达到一个不可控的状 态,所以我们还可以通过线程池来实现多个客户端请求的功能,因为线程池是可控的。

非阻塞模型

  • 不管是线程池还是单个线程,线程本身的处理个数是有限制的

  • 如果线程数太多会造成 CPU 上下文切换的开销。因 此这种方式不能解决根本问题

提出了NIO new IO

阻塞 IO

  • 客户端的数据从网卡缓冲区复制到内核缓冲区之前,服务端会一直阻塞

非阻塞 IO

  • 进程空间调用 recvfrom,如果这个时候内核缓冲区没有数据的话,就直接返回一个 EWOULDBLOCK 错误,然后应用程序通过不断轮询来检查这个 状态状态,看内核是不是有数据过来

I/O 复用模型

  • 通过一种机制(系 统内核缓冲 I/O 数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是 读就绪或写就绪),能够通知程序进行相应的读写操作

  • 什么是 fd:在 linux 中,内核把所有的外部设备都当成是一个文件来操作,对一个文件的读

    写会调用内核提供的系统命令,返回一个 fd(文件描述符)。而对于一个 socket 的读写也会有

    相应的文件描述符,成为 socketfd

IO 多路复用方式有【select、poll、epoll】,

select

  • 进程可以通过把一个或者多个 fd 传递给 select 系统调用,进程会阻塞在 select 操作上,这样 select 可以帮我们检测多个 fd 是否处于就绪状态。

  • 缺:

    • 么当前进程需要线性轮询所有的 fd,也就是监听的 fd 越多,性能开销越大

    • select 在单个进程中能打开的 fd 是有限制的,默认是 1024,对于那些需要支持单机上万的 TCP 连接来说确实有点少

epoll

  • epoll 是基于事件驱动方式来代替顺序扫描,因此性 能相对来说更高

  • 当被监听的 fd 中,有 fd 就绪时,会告知当前进程具体哪一

    个 fd 就绪,那么当前进程只需要去从指定的 fd 上读取数据即可

  • 【由于 epoll 能够通过事件告知应用进程哪个 fd 是可读的,所以我们也称这种 IO 为异步非

    阻塞 IO,当然它是伪异步的,因为它还需要去把数据从内核同步复制到用户空间中,真正的

    异步非阻塞,应该是数据已经完全准备好了,我只需要从用户空间读就行

多路复用的好处

  • I/O 多路复用可以通过把多个 I/O 的阻塞复用到同一个 select 的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。它的最大优势是系统开销小,并且不需要创建新的进程或者线程,降低了系统的资源开销

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值