网络是怎样连接的 第二章

系统中的协议栈如何处理数据发送请求

  1. 创建套接字

    • 协议栈的内部结构

       1. 最上面的部分是网络应用程序(也就是平时说的浏览器,Web服务器等等)	。
       2. 应用程序的下面是Socket库,其中包括解析器,解析器是用来想DNS服务器发出查询的。
       3. 在下面就是操作系统内部,其中包括协议栈。
       	协议栈的上班部分有两块,分别是负责用TCP协议收发数据的部分和负责用UDP协议收发数据的部分,它们会接受应用程序的委托执行收发数据的操作。
       	浏览器、邮件等一般应用程序收发数据使用TCP
       	DNS查询等收发较短的控制数据用UDP
       	下面一半用IP协议控制网络包收发操作的部分。在传送数据的时候,数据会被切成一个一个的网络包。而将网络包发送给通信对象的就是由IP来负责的。
       4. 最上面的部分是网络应用程序(也就是平时说的浏览器,Web服务器等等)	。
       5. IP下面的网卡驱动程序负责控制网卡硬件。
       6. 然后就是最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接受操作。 
      
    • 套接字实体

         套接字的实体就是通信控制信息。
         在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等。
         可以这样子说,这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。
         协议栈是根据套接字中记录的控制信息来工作的。
         可以在终端使用netstart -ano命令来查看套接字内容。
         有五个分别是Proto、Local Address、Foreign Address、State、PID
         1. Proto:协议类型。在使用TCP/IP协议通信的情况下,会显示TCP或UDP。
         2. Local Address 运行netstart命令的计算机本身(本地端)的IP地址和端口号。
         3. Foreign Address。通信对象(远程端)的IP地址和端口号。0.0.0.0表示还没有开始通信,没有绑定IP地址和端口号。此外,UDP协议中的套接字不绑定对方的地址和端口,因此显示*:*
         4. State 表示通信状态。
         5. PID 使用该套接字的的程序PID(进程标识符)。
      
    • 创建套接字的操作过程
      1. 应用程序调用socket申请创建套接字,协议栈根据应用程序的申请执行创建套接字的操作。

        首先协议栈会分配一个用于存放一个套接字所需的内存空间。因为记录控制信息的内存空间不是一开始就存在的,因此需要先开辟一块空间,相当于为控制信息准备了一个容器,准备好容器之后,在写入这一初始状态的控制信息。套接字的创建就完成了。
      

      2.将表示这个套接字的描述符告知应用程序。描述符相当于用来区分协议栈中多个套接字的号码牌。

        有许多套接字,你要确定哪个套接字是当前应用程序所需要的。那么就像你去酒店寄存行李,会给你行李箱上面贴一个牌子,然后再给你一个牌子,你就可以根据手中的牌子去找哪一个对应的行李箱。
      

      3.收到描述符之后,应用程序在向协议栈进行收发数据委托就需要提供这个描述符。

        因为套接字中记录了通信双方的信息以及通信处于何种状态,所以只要通过描述符找到了对应的套接字,协议栈就可以获取相应的消息了。这样子应用程序就不要每次都告诉协议栈应该和谁通信了。所有的信息都在套接字里面写着。只要找到套接字就可以了。
      
  2. 连接服务器

    • 连接具体进行怎样的操作
      通信双方交换控制信息,在套接字中(类似记录端口号和IP地址)这些必要信息并准备数据收发的一连串操作。

        服务器上,应用程序只知道创建套接字,然后就不知道干什么了,它不知道我需要找谁。
        而客户端知道我需要的通信对象是谁。
        那么就类似于客户端告诉服务器“我想和你通信,我的IP地址是xxxx我的端口号是xxx。”然后客户端就向服务器传达了一个咱俩开始通信的请求。
      

      上面这个就是客户端将IP地址和端口号告知服务器的过程就属于交换控制信息的例子。
      并且当执行数据收发操作时,还需要一块用来临时存放要收发数据的内存空间(被称为缓冲区)。

    • 协议栈如何工作
      控制信息中有两类,一类是客户端和服务器相互联络时交换的控制信息。另外一个就是保存在套接字中,用来控制协议栈操作的信息,应用程序传递来的信息以及从通信对象接收到的信息都会保存在这里,还有收发数据操作的执行状态等信息也保存在这里,协议栈会根据这些信息来执行每一步的操作。

    • 客户端与服务器如何进行交互
      操作这个过程,应该从应用程序调用Socket库的connect开始的。 connect(<描述符>,<服务器IP地址和端口号>,…)。

        1. 客户端创建一个包含表示开始数据收发操作的控制信息的头部。客户端也就是发送方	的套接字就准确找到了服务器(接收方)的套接字,也就是搞清楚了我应该连接哪个套接字,然后将头部的SYN比特设置为1,表示连接。
        2. TCP头部 创建好之后,接下来TCP模块会将信息传递给IP模块并委托它进行发送。IP发送网络包,通过网络到达服务器,服务器从处于等待状态的套接字中找到与TCP头部中记录的端口号相同的套接字就可以了。
        3. 找到之后套接字写入相应信息,将状态改为正在连接,然后服务器的TCP模块返回响应,也同样需要设置发送方和接收方的端口号和SYN比特,此外还需要设置一个ACK控制位设为1。表示接受到了网络包。
        4. 网络包返回到了客户端,通过TCP的头部来确认连接服务器的操作是否成功,如果SYN为1,表示连接成功,向套接字中写入服务器的IP地址,端口号等信息,将状态写为连接完毕。然后将ACK控制位设为1发回服务器,表示网络包接受到了。
        5. 服务器接收到返回包,连接操作完成。
      
  3. 收发数据
    两端的套接字完成连接之后,就进入到了收发消息的阶段了,在这个阶段,协议栈会将从应用程序收到的数据切成小块并发送给服务器,并且还要考虑到通信过程中可能会出错导致网络包丢失,协议栈还需要确认切分成的每个包是否已经送达服务器,对于没有送达的包要重新发送一次。
    当控制流程从connect回到应用程序之后,就进入到数据收发阶段。数据收发操作从应用程序调用write将要发送的数据交给协议栈开始的,协议栈收到数据后执行发送操作。

     	 1. 协议栈并不关心数据的内容,在它看来发送的数据就是一定长度的二进制字节序列。
     	 2. 协议栈接收到数据会先放到缓冲区,然后究竟传多少数据由应用程序判断,判断因素有俩:每个网络包可以容纳的数据长度和时间。究竟以达到MSS在发送,还是达到等待时间之后就发送由操作系统决定。
     	 3. 由于有时候数据包太大,会进行拆分发送。网络包装好数据发给服务器,TCP要先确认,然后发送操作才结束。
     	 4. TCP要确认对方是否收到网络包,以及当对方没收到时进行重发的功能。
     	 5. TCP在拆分数据时,会先算好每一块数据相当于从头开始的第多少个字节,然后吧这个算好的字节数写到TCP头部,然后接收方吧收到的字节数写入ACK号发送给发送方。
     	 6. 上面操作就是发送方说“现在发送的是从多少字节开始的,一共有多少字节。”接收方说“到第多少字节的数据我都收到了”,这个返回ACK号的操作称为确认响应。
     	 7. 因为如果都是默认从1开始,就很容易被人利用到。所以采用随机位置开始 ,这个随机位置开始就是最开始说的SYN控制位,就是在这一步将初始值告知的。其实就是SYN设为1的时候,还需要同时设置序号字段的初始值。
     	 8. 以上说了客户端向服务器发送数据的情形。然后服务器发送给客户端也是一样的。服务器收到之后计算出另一个序号,然后将序号和数据发送给客户端,客户端收到之后计算ACK号返回给服务器。
    

    TCP采用这样子确认对方是否收到了数据,在得到对方确认之前,发送过的包都会保存在缓存区,如果对方没有返回某些包对应的ACK号就会重新发送。

  4. 从服务器断开连接并删除套接字
    收发消息的操作全部结束之后,接下来要断开服务器的连接并删除套接字,断开操作的本质是当消息收发完成后客户端和服务器相互进行确认的过程。
    以服务器发起断开过程为例。

     1. 服务器的应用程序调用Socket库的close程序,将控制位的FIN比特设为1,协议栈委托IP模块发送给客户端。
     2. 客户端接收到服务器发来的FIN为1的TCP头部,客户端协议栈会讲自己的套接字状态标记为进入断开操作状态。
     3. 客户端向服务器返回一个ACK号。
     4. 客户端段发送一个FIN为1.
     5. 服务器返回一个ACK号。
     6. 双方都断开连接。
    

    在断开之后不会立即删除套接字,而是等上几分钟。为的是防止一端的返回的ACK号丢失,另一方就是重发,但是此时丢失ACK号的一方已经删除了套接字,然后又重新在同一端口号创建一个套接字,那么新建的会接收。防止这种情况的发生所以要等待一段时间。

  5. IP与以太网的包收发操作
    实际的网络包收发过程
    协议栈会与网卡进行配合,将数据切分成小块并封装成网络包,再将网络包转换成电信号或者光信号发送出去。
    具体:
    1. 发送方将包的目的地,访问的的服务器IP地址写入IP头部中,IP协议根据这个地址查找包的传输方向,从而找到下一个路由器的位置。
    2. IP协议查找下一个路由器的MAC地址,将这个地址写入MAC头部。
    3. IP协议委托以太网协议把包发送过去。
    4. 传输过程中,会经过集线器,这个是判断包接下来向什么地方传输。里面有一个表,然后根据以太网头部中记录的目的地信息查处方向。
    5. 到达了下一个路由器。再查出下一个路由器的MAC地址,然后写入MAC头部。。。重复。
    6. 最后到达目的地。

  6. 用UDP协议收发数据的操作
    UDP 的必要性以及与TCP的差异性
    UDP适用与一些一个包就可以把此次所需要的全部数据发送,即使丢失也只是一个包,而不是跟TCP一样全部重发。例如DNS查询等交换控制信息的操作。
    UDP不需要确认 ,只要在应用程序获取的数据的前面加上UDP头部,然后交给IP发送就可以了。接收就是根据IP头部的接收方和发送方IP地址以及UDP头部中的接收方和发送方端口号找到响应的套戒指将数据交给相应的应用程序就可以了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值