计算机网络基础知识

  下面是目前存在的三种网络协议模型,其中OSI模型的七层协议体系结构的概念是比较清楚的,理论也较完整,但是它实现起来比较复杂且又不实用,而TCP/IP四层体系结构相比来说是较容易实现的,所以目前也得到了非常广泛的应用。但由于TCP/IP是一个四层的体系结构图,只包含应用层,运输层,网际层和网络接口层,而网络接口层又没有太多具体内容,因此一般教学方面采用折中的办法,即综合OSI和TCP/IP的优点,采用一种五层协议的体系结构,这样既能阐述清楚原理,也方便大家理解。下面我们就来对比学习一下,简述下每个模型中每一个层级的原理和作用。

一,OSI七层模型

第一层:物理层
  在OSI参考模型中,物理层(Physical Layer)是参考模型的最低层,也是OSI模型的第一层。
  物理层的主要功能是:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
  物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。
第二层:数据链路层
  数据链路层(Data Link Layer)是OSI模型的第二层,负责建立和管理节点间的链路。该层的主要功能是:通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路。
  在计算机网络中由于各种干扰的存在,物理链路是不可靠的。因此,这一层的主要功能是在物理层提供的比特流的基础上,通过差错控制、流量控制方法,使有差错的物理线路变为无差错的数据链路,即提供可靠的通过物理介质传输数据的方法。
  该层通常又被分为介质访问控制(MAC)和逻辑链路控制(LLC)两个子层。

  MAC子层的主要任务是解决共享型网络中多用户对信道竞争的问题,完成网络介质的访问控制;

  LLC子层的主要任务是建立和维护网络连接,执行差错校验、流量控制和链路控制。
  数据链路层的具体工作是接收来自物理层的位流形式的数据,并封装成帧,传送到上一层;同样,也将来自上层的数据帧,拆装为位流形式的数据转发到物理层;并且,还负责处理接收端发回的确认帧的信息,以便提供可靠的数据传输。
第三层:网络层
  网络层(Network Layer)是OSI模型的第三层,它是OSI参考模型中最复杂的一层,也是通信子网的最高一层。它在下两层的基础上向资源子网提供服务。其主要任务是:通过路由选择算法,为报文或分组通过通信子网选择最适当的路径。该层控制数据链路层与传输层之间的信息转发,建立、维持和终止网络的连接。具体地说,数据链路层的数据在这一层被转换为数据包,然后通过路径选择、分段组合、顺序、进/出路由等控制,将信息从一个网络设备传送到另一个网络设备。
  一般地,数据链路层是解决同一网络内节点之间的通信,而网络层主要解决不同子网间的通信。例如在广域网之间通信时,必然会遇到路由(即两节点间可能有多条路径)选择问题。 

在实现网络层功能时,需要解决的主要问题如下:
   寻址:数据链路层中使用的物理地址(如MAC地址)仅解决网络内部的寻址问题。在不同子网之间通信时,为了识别和找到网络中的设备,每一子网中的设备都会被分配一个唯一的地址。由于各子网使用的物理技术可能不同,因此这个地址应当是逻辑地址(如IP地址)。
   交换:规定不同的信息交换方式。常见的交换技术有:线路交换技术和存储转发技术,后者又包括报文交换技术和分组交换技术。
   路由算法:当源节点和目的节点之间存在多条路径时,本层可以根据路由算法,通过网络为数据分组选择最佳路径,并将信息从最合适的路径由发送端传送到接收端。
   连接服务:与数据链路层流量控制不同的是,前者控制的是网络相邻节点间的流量,后者控制的是从源节点到目的节点间的流量。其目的在于防止阻塞,并进行差错检测。
第四层:传输层
  OSI下3层的主要任务是数据通信,上3层的任务是数据处理。而传输层(Transport Layer)是OSI模型的第4层。因此该层是通信子网和资源子网的接口和桥梁,起到承上启下的作用。
  该层的主要任务是:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。传输层的作用是向高层屏蔽下层数据通信的细节,即向用户透明地传送报文。该层常见的协议:TCP/IP中的TCP协议、Novell网络中的SPX协议和微软的NetBIOS/NetBEUI协议。
  传输层提供会话层和网络层之间的传输服务,这种服务从会话层获得数据,并在必要时,对数据进行分割。然后,传输层将数据传递到网络层,并确保数据能正确无误地传送到网络层。因此,传输层负责提供两节点之间数据的可靠传送,当两节点的联系确定之后,传输层则负责监督工作。综上,传输层的主要功能如下:
  传输连接管理:提供建立、维护和拆除传输连接的功能。传输层在网络层的基础上为高层提供“面向连接”和“面向无接连”的两种服务。
  处理传输差错:提供可靠的“面向连接”和不太可靠的“面向无连接”的数据传输服务、差错控制和流量控制。在提供“面向连接”服务时,通过这一层传输的数据将由目标设备确认,如果在指定的时间内未收到确认信息,数据将被重发。
监控服务质量。
第五层:会话层
  会话层(Session Layer)是OSI模型的第5层,是用户应用程序和网络之间的接口,主要任务是:向两个实体的表示层提供建立和使用连接的方法。将不同实体之间的表示层的连接称为会话。因此会话层的任务就是组织和协调两个会话进程之间的通信,并对数据交换进行管理。
  用户可以按照半双工、单工和全双工的方式建立会话。当建立会话时,用户必须提供他们想要连接的远程地址。而这些地址与MAC(介质访问控制子层)地址或网络层的逻辑地址不同,它们是为用户专门设计的,更便于用户记忆。域名(DN)就是一种网络上使用的远程地址例如:www.3721.com就是一个域名。会话层的具体功能如下:
  会话管理:允许用户在两个实体设备之间建立、维持和终止会话,并支持它们之间的数据交换。例如提供单方向会话或双向同时会话,并管理会话中的发送顺序,以及会话所占用时间的长短。
  会话流量控制:提供会话流量控制和交叉会话功能。
  寻址:使用远程地址建立会话连接。l
  出错控制:从逻辑上讲会话层主要负责数据交换的建立、保持和终止,但实际的工作却是接收来自传输层的数据,并负责纠正错误。会话控制和远程过程调用均属于这一层的功能。但应注意,此层检查的错误不是通信介质的错误,而是磁盘空间、打印机缺纸等类型的高级错误。
第六层:表示层
  表示层(Presentation Layer)是OSI模型的第六层,它对来自应用层的命令和数据进行解释,对各种语法赋予相应的含义,并按照一定的格式传送给会话层。其主要功能是“处理用户信息的表示问题,如编码、数据格式转换和加密解密”等。表示层的具体功能如下:
  数据格式处理:协商和建立数据交换的格式,解决各应用程序之间在数据格式表示上的差异。
  数据的编码:处理字符集和数字的转换。例如由于用户程序中的数据类型(整型或实型、有符号或无符号等)、用户标识等都可以有不同的表示方式,因此,在设备之间需要具有在不同字符集或格式之间转换的功能。
  压缩和解压缩:为了减少数据的传输量,这一层还负责数据的压缩与恢复。
  数据的加密和解密:可以提高网络的安全性。
第七层:应用层
  应用层(Application Layer)是OSI参考模型的最高层,它是计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。它在其他6层工作的基础上,负责完成网络中应用程序与网络操作系统之间的联系,建立与结束使用者之间的联系,并完成网络用户提出的各种网络服务及应用所需的监督、管理和服务等各种协议。此外,该层还负责协调各个应用程序间的工作。
  应用层为用户提供的服务和协议有:文件服务、目录服务、文件传输服务(FTP)、远程登录服务(Telnet)、电子邮件服务(E-mail)、打印服务、安全服务、网络管理服务、数据库服务等。上述的各种网络服务由该层的不同应用协议和程序完成,不同的网络操作系统之间在功能、界面、实现技术、对硬件的支持、安全可靠性以及具有的各种应用程序接口等各个方面的差异是很大的。应用层的主要功能如下:
  用户接口:应用层是用户与网络,以及应用程序与网络间的直接接口,使得用户能够与网络进行交互式联系。
实现各种服务:该层具有的各种应用程序可以完成和实现用户请求的各种服务。

 OSI7层模型的小结
  由于OSI是一个理想的模型,因此一般网络系统只涉及其中的几层,很少有系统能够具有所有的7层,并完全遵循它的规定。
在7层模型中,每一层都提供一个特殊的网络功能。从网络功能的角度观察:下面4层(物理层、数据链路层、网络层和传输层)主要提供数据传输和交换功能,即以节点到节点之间的通信为主;第4层作为上下两部分的桥梁,是整个网络体系结构中最关键的部分;而上3层(会话层、表示层和应用层)则以提供用户与应用程序之间的信息和数据处理功能为主。简言之,下4层主要完成通信子网的功能,上3层主要完成资源子网的功能。

二,五层协议

第一层——物理层:物理层就是将两端系统通过光缆,电缆,无线电波的方式连接起来,在物理层上所传输的单位就是比特,用于消除两台主机间的物理线路差距(例如主机A是电缆,主机B是光纤)。

  一台计算机与另一台计算机要进行通信,第一件要做的事是什么?当然是要把这台计算机与另外的其他计算机连起来啊,这样,我们才能把数据传输过去。例如可以通过光纤啊,电缆啊,双绞线啊等介质把他们连接起来,然后才能进行通信。
  也就是说,物理层负责把两台计算机连起来,然后在计算机之间通过高低电频来传送0,1这样的电信号。

第二层——数据链路层两台主机之间的数据传输,总是在一段一段的链路上传输的,这就需要专门的链路层的协议,在两个相邻结点之间传送数据时,数据链路层将网络层交下来的IP数据包组装成帧,然后在两个相邻结点的链路上传送。

  1、透明传输。
  2、差错检验
  3, 封装成帧,这一层,数据的单位称为 帧 (frame)

  前面说了,物理层它只是单纯的负责把计算机连接起来,并且在计算机之间传输0,1这样的电信号。如果这些0,1组合的传送毫无规则的话,计算机是解读不了的。一大堆0,1谁知道是什么鬼啊。
  因此,我们需要制定一套规则来进行0,1的传送。例如多少个电信号为一组啊,每一组信号应该如何标识才能让计算机读懂啊等等。于是,有了以太网协议。
  1. 以太网协议
  以太网协议规定,一组电信号构成一个数据包,我们把这个数据包称之为帧。每一个桢由标头(Head)和数据(Data)两部分组成。标头部分主要是一些说明数据,例如发送者,接收者等信息。而数据部分则是这个数据包具体的,想给接守者的内容。
  帧的大小一般为 64 - 1518 个字节。假如需要传送的数据很大的话,就分成多个桢来进行传送。
  大家想一个问题,一个桢的长度是 64~1518 个字节,也就是说桢的长度不是固定的,那你觉得标头部分的字节长度是固定的吗?它当然是固定的啊,假如不是固定的,每个桢都是单独发的,那计算机怎么知道标头是几个字节,数据是几个字节呢。所以标头部分的字节是固定的,并且固定为18个字节。
 

第三层——网络层:负责为分组交换网上的不同主机提供通信服务。在发送数据时,网络层把运输层产生的报文段或用户数据封装成分组或包。然后选择合适的路由,使源主机运输层所传下来的分组,能够通过网络中的路由器找到目的主机。具体功能包括寻址、路由选择、连接建立、保持和终止等。在发出传输请求的主机中的传输层向网络层递交传输报文段和目的地址,就像你通过快递服务寄件时提供目的地址一样。

     网络层的协议:IP协议,ARP协议,路由协议。

 

  把一台计算的的数据通过物理层和链路层发送给另一台计算机,究竟是谁发给谁的,计算机与计算机之间如何区分,你总得给他们一个唯一的标识吧?于是,MAC 地址出现了。
  1. MAC 地址
  以太网规定所有连入网络的计算机都要有网卡数据包必须从一块网卡传送到另外一块网卡,网卡的地址(也叫MAC地址)就是数据包的发送地址和接收地址。
  MAC地址 由 48 个二进制位所构成(12为十六进制位),在网卡生产时就被唯一标识了。其中前24位二进制数是厂商编号,后六个是网卡流水号。
  2. 广播与ARP协议
   

 

  如图,假如计算机 A 知道了计算机 B 的 MAC 地址,然后计算机 A 想要给计算机 B 传送数据,虽然计算机 A 知道了计算机 B 的 MAC 地址,可是它要怎么给它传送数据呢?计算机 A 不仅连着计算机 B,而且计算机 A 也还连着其他的计算机。 虽然计算机 A 知道计算机 B 的 MAC ,可是计算机 A 却不知道知道计算机 B 是分布在哪边路线上,为了解决这个问题,于是,有了广播的出现。
  (1). 广播  

 

  在同一个子网中,计算机 A 要向计算机 B 发送一个数据包,这个数据包会包含接收者的 MAC 地址。当发送时,计算机 A 是通过广播的方式发送的,这时同一个子网中的计算机 C, D 也会收到这个数据包的,然后收到这个数据包的计算机,会把数据包的 MAC 地址取出来,与自身的 MAC 地址对比,如果两者相同,则接受这个数据包,否则就丢弃这个数据包。这种发送方式我们称之为广播,就像我们平时在广场上通过广播的形式呼叫某个人一样,如果这个名字是你,你就理会一下,如果不是你,你就当作听不见。
  (2). ARP地址解析协议
  那么问题来了,计算机 A 是如何知道计算机 B 的 MAC 地址的呢?答案是使用ARP协议,我们先讲一下ARP协议的原理。

 

  • 假如计算机A,B处于同一个子网之中,计算机A要给计算机B发送数据时。我们先通过广播的形式给同一个子网中的每台电脑发送一个数据包(当然,这个数据包会包含接收方的IP地址)。当这些计算机收到这个数据包之后,会取出IP地址与自身的对比,如果相同,则把自己的MAC地址回复给对方,否则就丢弃这个数据包。这样,计算机A就能知道计算机B的MAC地址了。

 

  可能有人会问,知道了MAC地址之后,发送数据是通过广播的形式发送,询问对方的MAC地址也是通过广播的形式来发送,那其他计算机怎么知道你是要传送数据还是要询问MAC地址呢?其实在询问MAC地址的数据包中,在对方的MAC地址这一栏中,填的是一个特殊的MAC地址,其他计算机看到这个特殊的MAC地址之后,就能知道广播想干嘛了。

 

    • 假如两台计算机的IP不是处于同一个子网之中,这个时候,我们就会把数据包发送给网关,然后让网关让我们进行转发传送。

 

  上面我们有说到子网这个关键词,实际上我们所处的网络,是由无数个子网络构成的。因为只有在同一个网络下的端系统才能通过广播的方式发送数据,也就是广播的时候,只有同一个子网里面的计算机能够收到。为此我们引入了网络层协议,使得位于不同的子系统的两个主机也可以进行通信。不在同一个子系统的主机,我们是采用“路由”(如何向不同的子网络发送数据包)的方式发送数据。
  可能许多人就在想既然这么麻烦,为什么要引进子网的概念呢?假如没有子网这种划分的话,计算机 A 通过广播的方式发一个数据包给计算机 B , 其他所有计算机也都能收到这个数据包,然后进行对比再舍弃。那么世界上有那么多的计算机,每一台计算机都能收到其他所有计算机的数据包,那还其他计算机不得奔溃,根本就没有时间处理自己的业务。 因此产生了子网这么一个东西。

  通过上面的了解,我们已经知道了当两个要通信的计算机是同一个子网的,那我们就用广播的形式把数据传送给对方,如果不是同一个子网的,我们就会把数据发给网关,让网关进行转发。
  那么问题来了,我们如何区分哪些 MAC 地址是属于同一个子网的呢?为了解决这个问题,于是,有了 IP 协议。
  3. IP协议
  IP协议,它所定义的地址,我们称之为IP地址。IP协议有两种版本,一种是 IPv4,另一种是 IPv6。不过我们目前大多数用的还是 IPv4,我们现在也只讨论 IPv4 这个版本的协议。
  这个 IP 地址由 32 位的二进制数组成,我们一般把它分成4段的十进制表示,地址范围为0.0.0.0~255.255.255.255。
  每一台想要联网的计算机都会有一个IP地址。这个IP地址被分为两部分,前面一部分代表网络部分,后面一部分代表主机部分。并且网络部分和主机部分所占用的二进制位数不是固定的。假如两台计算机的网络部分是一模一样的,我们就说这两台计算机是处于同一个子网中。而网络部分我们通常是通过子网掩码来计算的,子网掩码也是由32位二进制数组成,子网掩码的网络部分全为1,主机部分全为0,通过将IP地址和子网掩码进行每位相与,得出的结果就是网络部分。例如 192.168.43.1 和 192.168.43.2, 假如这两个 IP 地址的网络部分为 24 位,主机部分为 8 位,则子网掩码都为 11111111.11111111.11111111.00000000,即255.255.255.0,通过计算可知他们的网络部分都为 192.168.43.0,所以他们处于同一个子网中。
  

  4. DNS服务器
  这里再说一个问题,我们是如何知道对方计算机的IP地址的呢?这个问题可能有人会觉得很白痴,心想,当然是计算机的操作者来进行输入了。这没错,当我们想要访问某个网站的时候,我们可以输入IP来进行访问,但是我相信绝大多数人是输入一个网址域名的,例如访问百度是输入 www.baidu.com 这个域名。其实当我们输入这个域名时,会有一个叫做DNS服务器的家伙来帮我们解析这个域名,然后返回这个域名对应的IP给我们的。
  因此,网络层的功能就是让我们在茫茫人海中,能够找到另一台计算机在哪里,是否属于同一个子网等。

第四层——运输层:该层的任务是负责向两台主机中进程之间的通信提供通用的数据传输服务,负责将应用层的报文向目的地传送,还要确保传 输差错控制和流量控制。在因特网中,有两个传输协议,即TCP和UDP,可提供端到端的、可靠的或者不可靠的传输。

     运输层主要使用以下两种协议: 
      (1) 传输控制协议TCP(Transmission Control Protocol):面向连接的,数据传输的单位是报文段,能够提供可靠的交付。 
      (2) 用户数据包协议UDP(User Datagram Protocol):无连接的,数据传输的单位是用户数据报,不保证提供可靠的交付,只能提供“尽最大努力交付”。

  通过IP地址和MAC地址我们可以确定要进行通信的主机,可是,主机B里面有各种各样的应用程序,主机该如何知道这些数据是给那个应用程序的呢?这个时候就需要端口(Port)了,通过端口我们就可以确定要通信的应用程序。也就是说,我们在从计算机A传数据给计算机B的时候,还得指定一个端口,以供特定的应用程序来接受处理。因此我们常说传输层的功能就是建立端口到端口的通信,而网络层的功能只是建立主机到主机的通信,只有确定了主机和端口,才能实现程序之间的准确通信。
  这个时候可能有人会说,我输入IP地址的时候并没有指定一个端口啊。其实呢,对于有些传输协议,已经有设定了一些默认端口了。例如http的传输默认端口是80,这些端口信息也会包含在数据包里的。
  传输层最常见的两大协议是 TCP 协议和 UDP 协议,其中 TCP 协议与 UDP 最大的不同就是 TCP 提供可靠的传输,而 UDP 提供的是不可靠传输。

第五层——应用层是体系的最高层,主要任务是通过应用进程之间的交互来完成特定的网络应用。
     应用层协议:支持万维网应用的HTTP协议,支持电子邮件的SMTP协议,支持文件传送的FTP协议。
  终于说到应用层了,应用层这一层最接近我们用户了。虽然我们收到了传输层传来的数据,可是这些传过来的数据五花八门,有html格式的,有mp4格式的,各种各样。你确定你能看的懂?
  因此我们需要指定这些数据的格式规则,收到后才好解读渲染。例如我们最常见的 Http 数据包中,就会指定该数据包是 什么格式的文件了。

三,在五层模型中数据传输的过程

数据的整条发送链是:
1、某进程(也就是在应用层)准备好待传输数据,若目的地址是域名则要先通过DNS解析成IP地址。
2、交付到运输层(TCP/UDP层),运输层对数据进行适当的分组等操作,后对每一个分组数组加上首部形成报文段(或用户数据报),首部包括源地址、源端口、目的地址、目的端口和一些其他的诸如校验和等数据
3、交付到网际层(IP层),对分组数据加上首部形成IP数据报,首部包括源地址、目的地址(跟运输层的目的地址不同,运输层的目的地址是数据要传送的最终地址,而该目的地址是通过路由表信息得出,是该数据下一步该转移的目的计算机)和校验和等数据
4、交付到数据链路层(mac层),先是对把数据封装成帧(也就是添加首部[SOH]和尾部[EOT]),然后进行透明传输(也就是封装的数据里面,如果出现首部SOH和尾部EOT这样的数据,对其进行转义,也就是加上ESC转义字符,这种方法称为字节/字符填充)
5、交付到物理层,根据数据链路层的mac知道要传输到目的计算机,通过特定的传输介质传送到下一个地址
6、若源主机与最终目的主机在同一个网段,则该地址是最终的目的主机,开始接收数据,进入第7步骤,若源主机和最终目的主机不在同一个网段,进入第11步骤
7、交付到数据链路层,对数据进行卸装,该层会对接收的数据进行差错检测,有差错的数据都会被丢弃
8、交付到IP层,解帧校验
9、交付到运输层,在该主机上,根据端口找到对应的应用,当使用的TCP协议时,提供一种面向连接的可靠的传输服务,可以说是建立了一个虚拟通道,源主机的数据通过该虚拟通道进行传输;若是使用的UDP协议时,提供一种面向的非连接的尽最大努力的不可靠的传输服务,数据传输快,但是无法保证数据100%传输。
10、建立了传输连接后,应用开始接收数据,发送方数据和接收方都必须满足相同的标准应用层协议,如http、ftp、smtp等,通过标准协议应用即可正确的接收源主机发送过来的数据。
11、该计算机不是最终主机,那该计算机就是路由器也就是用于转发分组数据的中转站,首先接收数据的处理同步骤7和8一样,然后接下来的流程又是如同步骤3,
12、如此循环直至找到最终主机,将数据传送到目的应用

四,TCP/UDP的区别

UDP的包头:

(1)源端口号:在需要对方回信时用,不需要时全为0。

(2)目的端口:在终点交付报文时必须使用。

(3)长度:UDP用户数据的长度,其最小值是8(仅有部首)。

(4)检验和:检测UDP用户数据报在传输中是否有错,有错就丢弃。

用户数据报协议UDP的特点:

(1)面向无连接的网络传输协议。即A向B发送消息时,不需要A与B进行建立连接,只要 A 知道 B 的地址(IP 和 port )就可以传输数据,当发送完数据时也没有连接可释放,因此减少了开销和发送数据之前的延时。

(2)具有较好的实时性。由于不需要连接所以每一个用户数据报的首部会非常的小,所以传递会非常的快速便捷,但是由于面向无连接的擦混熟,A如果向B发数据时,数据丢失,B是不知道的,所以这种传输不安全!主要应用于直播,视频聊天等等。
(3)不可靠传输,尽最大努力交付。因为UDP没有确认机制和重传机制,因此如果数据发生丢失是不会通知给上层的。
(4)无拥塞控制; 不会因为网络拥塞导致发送速率降低,但会因为网络拥塞而造成部分数据丢失,对于某些实时的应用很重要, 比如ip通话 视频会议等
(5)提供全双工通信。并支持一对一、一对多、多对一和多对多的交互通信;因为不需要建立连接 所以在发送的时候其实可以发给任意用户

(6)面向数据包/报文的。发送方的UDP对应用程序交下来的报文,既不拆分,也不合并,而是在添加首部后就向下交付IP层。而接收方的UDP对IP层交上来的报文,去除部首后就原封不动的交给上层。

(6)首部开销小(只有四个字段:源端口、目的端口、长度、检验和),共8个字节(一个字节由8个二进制位组成)。

(7)适合实时传送

TCP包头:

TCP的特点:
(1)面向连接的:首先A和B发消息时A和B就要建立连接,建立连接之后才可以相互发消息,在发消息之前要建立好相对应的管道。再断开连接时,同样也需要相互断开
(2)可靠的,保证数据正确性:TCP的首部相对复杂和大了许多,在首部存在着控制连接的数据位。例如:检验和来确认这段消息的接收方是谁,利用ack来确认回复的是哪一个消息,下一个想要收到的是什么消息,利用seq来对信息进行编号,来判断数据是否缺少某一信息以及大数报分割成小的数据报进行传输。使用拥塞控值机制来控制向网络发送数据的多少,来避免报文阻塞在网络中。所以通过TCP连接传送的数据,无差错,不丢失,不重复。
(3)每一条TCP连接只能是点对点的(一对一),连接建立好之后只能连接建立的双方之间进行通信。

(4)提供全双工通信,即通信双方可以同时发送信息和接收信息,如打电话。
(5)面向字节流。 那这里字节流我想应该都不陌生,就是我们之间说过的哪个字节流。但是稍有不同的是他是操作文件的 ,所以要通过节点流是进行网络传输的。
(6)首部开销较大 占20字节

(7)适合传输大量的数据

 

五, TCP协议详述
1.TCP 的包头格式如下:

其中包含如下内容:
源端口:占用16bit位,表示发送发主机进程占用的端口号,通过端口号可以找到主机上某一个应用程序。

目的端口:占用16bit位,表示目的方的端口号。
序号:32位,Seq序号,对发送的数据进行编码,接收方返回的确认序号就是发送方下一次发送的序号。
确认序号:32位,ack序号,发出去的包应该有确认,这样能知道对方是否收到,如果没收到就应该重新发送,这个解决的是丢包的问题。一般接收端发送给客户端的确认号是客户端发送来的seq号+1,表示这标编号之前的数据成功接收。
状态位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
(A)紧急URG:紧急指针是否有效。若为1,表示某一位需要被优先处理。
(B)确认ACK:确认序号是否有效,为1时表示有效。
(C)推送PSH:提示接收端应用程序立即从TCP缓冲区把该数据读走。
(D)复位RST:对方要求重新建立连接,复位。
(E)同步SYN:置为1时发起一个新连接。
(F)终止FIN:置为1时,释放一个连接。
因为 TCP 是面向连接的,因此需要双方维护连接的状态,这些状态位的包会引起双方的状态变更。
窗口大小:占用16bit位,TCP 中用来做流量控制的,通过窗口可以告知发送方窗口的大小,通过动态的控制发送窗口的大小来控制发送到网络中包的大小,网络通常时发送大的数据包,网络发送拥堵时发送小的数据包。需要通信双方各声明一个窗口,标识自己当前的处理能力。

检验和:占用16bit,通过对首部和数据进行检验来判断当前包是否正确。

2, TCP保证可靠性的传输手段

  校验和:报文的检验和用来保证当前传输包的完整性。

  确认应答:客户端每次给服务器发送SYN,服务器会给客户端返回ACK,告诉客户端自己接收到消息,从而保证了客户端的每次请求都可以成功可靠的发送给服务端。
  超时重传:当主机A给主机B发送一个数据的时候,主机A会启动一个计时器,由于网络的原因造成主机B发送给主机A的确认应答报文丢失,这时候主机A因为在超时之前没有收到主机B的确认消息,就会进行重传,并重新启动计时器。
  流量控制(滑动窗口:控制双方的发送速率,避免数据丢失。在TCP报头中包括了一个窗口大小的字段用来表示自己可以接收的最大报文数量。当主机A向主机B发送一个报文的时候,每次都会看一下主机B的接受窗口,主机B接收到主机A发送给自己的数据之后,此时会将自己的接受窗口写入到TCP报头中窗口字段中,A接受到主机B发送给自己的报文之后,首先先看一下对方窗口大小,如果这个窗口大小比较大了,此时主机A会增加发送数据的数量,如果发现接受方的接受窗口比较小的时候,此时就会减少发送数据的量,当发现对方的接受窗口为0的时候,此时就会停止自己发送报文。当过一段时间,发送方A会给接收方B发送探测数据,以便知道对方的接受窗口的大小。
  拥塞控制:网络上连接了许多的数据,如果一开始的时候各个主机直接给网络发送很多的数据,此时势必会造成网络拥塞.TCP规定了一个拥塞窗口,表示当前网络能够接受多大数据,每次发送方在发送的时候都会将对方的窗口大小和拥塞窗口进行比较,将较小的数据作为自己的发送窗口。同时在发送的时候规定拥塞窗口大小为1,每接收到一个应答便将拥塞窗口加1,当拥塞窗口的大小大于一个阀值的时候,此时将变为线性增长,同时每次超时重传的时候阀值会降为原来的一半.同时将拥塞窗口变为1。

2.1超时重传

 

通过上面的描述可知,TCP在保证可靠传输时使用了超时重传机制,那超时重传的计时器需要设置为多长时间?

 

我们先来了解一下什么是 RTT(Round-Trip Time 往返时延),从下图我们就可以知道:

 

 

RTT 就是数据从网络一端传送到另一端并得到返回确认消息所需的时间,也就是包的往返时间。而超时重传时间 RTO  (Retransmission Timeout 超时重传时间)的值应该略大于报文往返 RTT 的值。接下来就分析下为什么是略大于而不是小于??

 

假设在重传的情况下,超时重传时间 RTO 「较长或较短」时,会发生什么事情呢?

 

 

上图中有两种超时时间不同的情况:

 

  • 当超时时间 RTO 较大时,重发就慢,丢了老半天才重发,没有效率,性能差;
  • 当超时时间 RTO 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。

 

这也就是为什么超时重传时间是略大于RTT的原因了!!!

 

2.2滑动窗口协议:

  滑动窗口解决的是流量控制的的问题,就是如果接收端和发送端对数据包的处理速度不同,如何让双方达成一致。接收端的缓存传输数据给应用层,但这个过程不一定是即时的,如果发送速度太快,会出现接收端数据overflow,流量控制解决的是这个问题。

  

 

  下面描述A向B发送数据时,A窗口和B窗口的滑动过程:

  

  

 

 

窗口关闭:如果窗口大小为 0 时,就会阻止发送方给接收方传递数据,直到窗口变为非 0 为止,这就是窗口关闭。

窗口关闭潜在的危险:接收方向发送方通告窗口大小时,是通过 ACK 报文来通告的。那么,当发生窗口关闭时,接收方处理完数据后,会向发送方通告一个窗口非 0 的 ACK 报文,如果这个通告窗口的 ACK 报文在网络中丢失了,此时发送不知道情况,仍然一直等待接收方的非 0 窗口通知,接收方也一直等待发送方的数据,如不不采取措施,这种相互等待的过程,会造成了死锁的现象。所以之后引入了窗口探测!当发送端收到接收端发来的窗口为0的ACK通知时,就会开启一个计时器,在超时前未收到接收方的窗口非0ACK通知,发送方就会探测接收端窗口,如果仍然为0,则发送端重启计时器,如果不为0,这时就可以认为接收端允许发送数据了,但窗口非 0 的 ACK 报文在发送途中可能丢失了,于是发送端开始接着发送数据,这样就避免了死锁的情况了。

窗口探测

  • 如果接收窗口为 0,那么收到这个报文的一方就会重新启动持续计时器;
  • 如果接收窗口不是 0,发送方开始接着发送数据,那么就避免了死锁的局面。

窗口探查探测的次数一般为 3 此次,每次次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发 RST 报文来中断连接。

 与滑动窗口相同的还有停止等待协议,连续ARQ协议(回退N协议),选择重传协议。

2.3停止等待协议

   当发送窗口和接收窗口都等于1时,就是停止等待协议。发送端给接收端发送数据,并停止发送新的数据包,开启计时器,等待接收端确认回复ACk。数据包在计时器超时之前得到确认,那么计时器就会关闭,并发送下一个数据包。如果计时器超时,发送端就认为数据包丢失或被破坏,需要重新发送之前的数据包,所以数据包在得到确认之前,发送端需要存储数据包的副本。 
  因此停止等待协议是发出一个帧后得到确认才发下一个,降低了信道的利用率。

2.3.1无差错情况

 2.3.2数据丢失

2.3.3 ACK丢失

 

 2.3.4ACK迟到

 

 

2.4ARQ协议(回退N协议)

  在发送完一个帧后,不用停下来等待确认,而是可以继续发送多个数据帧,这相对于停止等待协议必须收到前一个数据确认消息才可继续发送来说,大大减少了等待时间,整个通信的通吞吐量提高。 但如果前一个帧在超时时间内未得到确认,就认为丢失或被破坏,需要重发出错帧及其后面的所有数据帧。这样有可能有把正确的数据帧重传一遍,降低了传送效率。 线路很差时,使用退后N帧的协议会浪费大量的带宽重传帧。
2.5选择重传协议 

  后退n协议的另外一个问题是,当有错误帧出现后,总是要重发该帧之后的所有帧,毫无疑问在网络不是很好的情况下会进一步恶化网络状况。
  重传协议便是用来解决这个问题。原理也很简单,接收端总会缓存所有收到的帧,当某个帧出现错误时,只会要求重传这一个帧,只有当某个序号后的所有帧都正确收到后,才会一起提交给高层应用。重传协议的缺点在于接受端需要更多的缓存。选择重传协议可以避免重复传送那些正确到达接收端的数据帧。但是接收端要设置具有相当容量的缓存空间,这在许多情况下是不够经济的。

2.6 拥塞窗口

  出现拥塞的条件:

  

  若网络中有许多资源同时呈现供不应求,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。

 

  拥塞控制与流量控制的关系密切,流量控制往往是指点对点通信量的控制,是端到端的问题,而拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载,拥塞控制是一个全局性的过程,涉及到所有主机,所有路由器。

 

  流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么。一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大….所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。

 

  于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。

 

 2.6.1.慢开始与拥塞避免
       发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化,另外由于考虑到接受方的接收能力,所以发送窗口的大小等于拥塞窗口和接收窗口两者中较小的一个。
       慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
  旧的规定:初始拥塞窗口cwnd设置为1至2个发送方的最大报文段SMSS的数值;

  但新的规定:
  

 下面举例说明慢开始算法的原理:

    

 

  传输轮次指的是把所允许的报文段发送出去并得到确认的过程,从上图我们可以知道传输轮次中发送的报文段是不断增加的,跟拥塞窗口同步。(cwnd表示此次允许发送的报文段,也表示窗口的增加量)

       为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下:
  

       拥塞避免算法让拥塞窗口缓慢增长,在拥塞避免算法中,每经过一个传输轮次就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口按线性规律缓慢增长。
       无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢开始算法。如下图:

  

  

  

 下面是归纳出来的整个流程图:

      

      再次提醒这里只是为了讨论方便而将拥塞窗口大小的单位改为数据报的个数,实际上应当是字节。另外上面仅是考虑了对方有足够的缓存接收发来的数据,所以在正常情况下我们还需考率接收方窗口rwnd:

  

4.TCP 的三次握手

a.建立连接的过程
  所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:

(1)第一次握手:Client将报文的标志位SYN置为1,随机产生一个序号seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后,由报文中的标志位SYN=1知道Client在请求建立连接;Server会发送一个报文,其中标志位SYN和ACK都置为1,确认序号为ack=J+1,随机产生一个值seq=K(这样可避免黑客很容易猜到序列号而发起攻击),并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认报文后,检查ack为J+1,ACK为1,则再次发送一个报文,将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
需要注意的是:
(A)不要将确认序号ack与标志位中的ACK搞混了。
(B)确认方确认序号ack=发起方序号seq+1,两端配对

b.为什么建立连接是三次握手而不是两次握手或四次?

答:第三次是为了防止已经失效的连接请求报文段又突然传到服务端,而产生错误。例如A发送给B一个连接请求,但在网络传输过程中突然丢失或滞留,A因为迟迟没有接收到B的确认信息,就接着向B发送了一次请求,这次B正常接收,并返回给A确认报文段,A接着向B进行确认,成功后两者就进行通信,当通信完成后就释放连接了,然而这时候A之前发给B的那个消息突然又被B接收到了,B以为A又要跟他建立连接,如果是两次握手,当B发给A一个确认后,由于A知道这是之前被延误的消息,且两者之间的连接也已经建立过了,所以就不会理会了,但B却认为两者之间成功建立连接了,就等待A发送数据,这时候就白白浪费了B的资源。如果是三次握手,当A没有理会后,由于B没有再次收到A确认的消息,就会知道A并没有打算建立连接,所以就不会进行等待。至于为什么不是四次,因为三次完全可以成功建立连接了,使用第四次就会造成不必要的资源浪费。

5.SYN攻击:
在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击是一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:
#netstat -nap | grep SYN_RECV

6.TCP的四次挥手
  所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示。

  由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN报文来终止这一方向的连接,发送一个FIN报文只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是对方仍然可以发送数据,直到对方也发送了FIN报文。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN断开连接的报文,其中FIN置为1,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN报文后,发送一个ACK报文(ACK置为1)给Client,其中ack确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。这时Client已不能发送数据。但是Server还是可以给Client发数据,Client也还可以接收数据(半连接状态)。
(3)第三次挥手:若Server发送一个FIN报文,用来关闭Server到Client的数据传送,则Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:

a.为什么断开连接是四次挥手

因为TCP是全双工模式,断开连接是双方的事,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,当主机2收到主机1的确认后,之后彼此就会愉快的中断这次TCP连接。

为什么不是三次?

如果是三次,当主机2发送完信息,在发送FIN断开连接的报文时,在传输的过程中发生的丢失的情况,由于主机1没有收到报文,因为主机2还有消息未发送,就一直进行等待者,这就造成了失误发生。另外还有一种三次的情况是将中间主机2对主机1的确认报文和断开连接的报文合并发送,这样的话虽然避免了前面那种情况,但也还是有弊端,因为当主机1给主机2发送断开连接的请求时,有超时重传机制,需立即返回确认信息,但这时候主机2可能还有部分数据需要传给主机1,如果这时候断开,就会造成信息发送不完整的情况。

b.四次挥手的状态

FIN_WAIT_1:这个状态和FIN_WAIT_2状态都在再等待对方的回复,但是这两种状态是有区别的,FIN_WAIT_1就是主动方在ESTABLISHED状态的时候,想要主动关闭连接,向对方发送FIN报文,这时候就进入了FIN_WAIT_1状态。当他收到对方回复的ACK报文后,就进入了FIN_WAIT_2状态。 但是在实际操作中是很难遇到FIN_WAIT_1状态的,因为无论对方是什么情况都应该立刻回应ACK报文,但是FIN_WAIT_2状态还是可以在主动方中用netstat看到的。
FIN_WAIT_2:上面已经对FIN_WAIT_2讲解过了,当主动方进入FIN_WAIT_2时,就表示着半连接状态,也就是主动方还有数据要发给对方,这个数据就是之后的ACK,所有他要等一会儿才关闭连接。
CLOSE_WAIT:这个状态从表面也可以看出它的作用,就是等待关闭。当被动方接收到FIN时,会立刻回复一个ACK给对方,接下来就是进入CLOSE_WAIT状态。在这个状态中,被动方需要考虑自己还有没有数据要发送给对方,如果有可以继续发送,如果没有了就可以关闭连接了,发送一个FIN给对方。 这个状态其实也就是给自己一个缓冲的时间,让自己处理完需要处理的事,然后去关闭连接。
TIME_WAIT:这个状态就是一段时间后进行一些操作。当主动方收到了对方发来的FIN报文,并发出ACK报文,接下来就等2MSL就可以进入CLOSED状态了。其实,如果主动方在FIN_WAIT_1状态下,收到了对方的FIN+ACK标志的报文,就可以跳过FIN_WAIT_2状态直接进入TIME_WAIT状态了。
LAST_ACK:这个状态从表面不难不理解他的意思,这个状态就是被动方发送了FIN报文后,最后等待对方的ACK报文,收到ACK报文后就可以进入CLOSED状态了。
CLOSED:上面提到了几次这个状态,相比也猜出来了,这个状态表示的就是连接中断,已经关闭。

c.为什么需要TIME_WAIT?
  TIME_WAIT在四次挥手中有着不可替代的位置,如果没有TIME-WAIT,主动方就会直接进入CLOSED状态,如果因为网络中种种原因最后一次ACK丢失了,服务端因为迟迟没有收到客户端的确认消息,服务端就会重复FIN请求,(假设主动方是客户端,被动方是服务端)而这时候如果立即重新启启客户端且使用相同的端口,这时服务端发来的这个FIN就会被重新启动的客户端接收到,或者新启动的客户端向服务端发起请求的时候,因为服务端正在等待最后一次ACK,因此新连接请求发送的SYN就会被服务端认为时请求码错误,服务端就会回复RET重置连接。所以就需要主动方发送最后一次ACK之后进入TIME_WAIT状态,等待2MSL(两个报文最大生命周期),等待这段时间就是为了如果接收到了重发的FIN请求能够进行最后一次ACK回复,让在网络中延迟的FIN/ACK数据都消失在网络中,不会对后续连接造成影响。

d.那么为什么TIME_WAIT的时间是2MSL呢?
  客户端在收到服务端真正的关闭连接FIN请求后,会进入TIME_WAIT状态,并等待2MSL时间(相当于一个报文一来一回的时间),这是为了避免特殊情况的发生,因为假如客户端发给服务器的确认应答丢失,当服务端迟迟没有收到客户端的确认信息后,会重传FIN断开连接的报文,算上这个丢失报文的时间,再加上服务端重传FIN的时间(重传后客户端重新启动2MSL计时器),2MSL的时间就刚好足够使客户端收到重传的FIN报文段。所以客户端不能立即进入CLOSED状态,需等待2MSL时间。

6.TCP与UDP区别总结:
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP首部开销20字节;UDP的首部开销小,只有8个字节
6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
  

7.因为UDP是不可靠传输,那如何保证UDP的数据不丢失?

答:借鉴TCP的ACK机制:UDP发送的数据包,接收方收到之后回复一个确认包,发送端未接收到确认包,就认为数据丢失,然后再次重传数据。

六,Socket编程

1.tcp连接

服务端:

 1 public class TCPServer {
 2     public static void main(String[] args) {
 3         ServerSocket serverSocket=null;
 4         Socket socket=null;
 5         BufferedReader reader=null;
 6         try{
 7             //创建serversocket实例
 8             serverSocket=new ServerSocket();
 9             //绑定端口
10             serverSocket.bind(new InetSocketAddress(8888));
11             System.out.println("8888服务端启动了");
12             //等待客户端连接,返回的是socket实例,即客户端和服务端的实例
13             socket=serverSocket.accept();
14             //服务端来读取消息,从socket的流中读取数据
15             reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
16             char[] buffer=new char[1024];
17             int num;
18             while ((num=reader.read(buffer))!=-1){
19                 System.out.println("read..");
20                 System.out.println(buffer);
21             }
22         }catch (IOException e){
23             e.printStackTrace();
24         }finally {
25             try{
26                 if(reader!=null)reader.close();
27                 if(socket!=null)socket.close();
28                 if(serverSocket!=null)serverSocket.close();
29             } catch (IOException e) {
30                 e.printStackTrace();
31             }
32         }
33     }
34 }

客服端:

 1 public class TCPClient {
 2     public static void main(String[] args) {
 3         //创建Socket实例
 4         Socket socket=new Socket();
 5         try {
 6             //连接服务器
 7             socket.connect(new InetSocketAddress("127.0.0.1",8888));
 8             //发送数据给服务端,先得到socket的流,然后将数据写到流中
 9             OutputStream outputStream = socket.getOutputStream();
10             outputStream.write("hello".getBytes());
11         } catch (IOException e) {
12             e.printStackTrace();
13         }finally {
14             try {
15                 socket.close();
16             } catch (IOException e) {
17                 e.printStackTrace();
18             }
19         }
20     }
21 }

问题:对比上面客户端的代码和服务端的代码可以发现,在建立连接时,服务端需要绑定端口号,而客户端不需要绑定端口号,而是在连接时提供服务端的端口号和服务端的IP地址,为什么呢?

       1.服务器和客户端都需要端口号,但是服务器的端口是需要编程人员设置,而不是由系统自动分配(这就是为什么在服务端有这行代码serverSocket.bind(new InetSocketAddress(8888)))。那为什么要编程个人员自己设置呢?因为在服务端和客户端连接的过程中,客户端是主动连接的,而服务器是等待连接的,但是客户端要连接服务端就必须知道服务端的端口号和服务端的IP地址才行,所以只有编程人员自己设置了服务端的端口号,才会知道服务端的端口号是多少,如果是随机分配的,那么客户端也不知道系统分配的是哪个端口,客户端不知道服务器的端口,也就无法与服务端进行连接。

       2.客户端就不需要绑定端口了,服务端在和客户端连接后,系统随机分配一个端口号给客户端(当然也可以自己设置)。当客户端第一次向服务器发送数据时,客户端的端口号随同数据一起就给了服务器。服务器有了客户端的端口自然就可以向客户端发送数据。

注意:当客户端和服务端在同一台电脑上时,两个的IP地址是一样的,所以客户端建立连接时,只要知道服务器的端口号即可。但当两者不在同一个电脑上时,就需要先查看服务器端的IP地址,然后使用服务端的IP地址和端口号进行连接。

2.UDP连接

服务端:

public class UDPServer {
    public static void main(String[] args)throws Exception {
        //创建DatagramSocket实例
        DatagramSocket datagramSocket = new DatagramSocket();
        //发送数据封装
        String str = "hello java!";
        DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(), str.length(), new InetSocketAddress("127.0.0.1", 9999));
        //发送操作
        datagramSocket.send(datagramPacket);
        //关闭资源
        datagramSocket.close();
    }
}

客户端:

public class UDPClient {
    public static void main(String[] args) throws Exception{
        //创建DatagramSocket实例
        DatagramSocket datagramSocket=new DatagramSocket(9999);
        //接收数据
        byte[] bytes=new byte[1024];
        DatagramPacket datagramPacket=new DatagramPacket(bytes,1024);
        //接受操作
        datagramSocket.receive(datagramPacket);
        //取出数据
        String s=new String(datagramPacket.getData(),0,datagramPacket.getLength());
        System.out.println("取出数据:"+s);
        datagramSocket.close();
    }
}

  注意在UDP编程中,服务端发送数据时,必须确保客户端正在接收,否则就会出现数据丢失情况,因为服务端只管发,不管是否有人接。但接收数据方,不管有没有数据都可进行接收操作,没有接收到时,就会一直处于阻塞状态,有则进行接收。

七,IP协议报

     

 

 

 

        

        

     

      

八,IP地址划分和表现形式

        

     

九,路由控制
  IP地址中的网络地址部分用户进行路由控制,路由控制表记录着网络地址与下一步听该发送的路由器的地址。
  在发送IP报时,首先确定IP头部中的目标地址,在从路由控制表中找到与该地址具有相同网络地址的记录,根据该记录将IP地址妆发到响应的下一个路由器,如果路由器表中存在相同或网络地址的记录,就选择一个最吻合的网络地址。

如果在某一个路由表中没有匹配到网络地址,就会从默认的路由地址查找。
路由表的控制有两种方式:

  • 静态路由控制:是管理员手动设置
  • 动态路由控制:路由器与其他的路由器相互交互信息时自动刷新

十,IPv6
IPv6(IP version 6)解决IPv4地址耗尽的问题
IPv4地址长度是23位,4个8位字节
IPv6地址长度是128位,一般携程8个16位字节
IPv6包首部长度固定的值(40个字节)
IPv6标记: 一般将128比特位地址以每16比特位一组,每组用冒号(“:”)隔开表示,如果出现连续的0可以省略,用两个冒号(“::”)隔开,但是一个IP地址中只允许出现一次连续的冒号。

十一,DNS:域名解析
DNS:将域名解析为IP地址
一个域名有多个层次组成,包含顶级域名,二级域名,三级域名以及四级域名。

域名服务器分类:(域名服务器主要分为四类)
根域名服务器:解析顶级域名
顶级域名服务器:解析二级域名
权限域名服务器:解析区内的域名
本地域名服务器:默认域名服务器,可以在其中配置缓存
十二,域名解析过程
域名通过域名服务器解析使用递归和迭代两种方式:

  • 迭代方式:本地域名服务器向一个域名服务器发送域名解析请求之后,结果返回到本地域名服务器,然后本地域名服务器继续向其他的域名服务器请求解析。
  • 递归方式:请求的结果不是直接返回去,而是继续向前请求解析,最后的结果才会返回。

十三,经典面试题
从输入网址到获取页面的网络请求的过程?
• 域名解析
 1、先查找浏览器中缓存是否存在对应IP,浏览器会缓存DNS一段时间
 2、如果没找到,在从Hosts文件查找是否有域名和对应IP的信息
 3、如果没找,再从路由器中查找
 4、如果没找到,再从DNS缓存查找
 5、如果还是没找到,浏览器域名服务器会想根域名服务器查找域名对应的IP
• 网络传输通信
1、拿到IP之后进行通信,先和对方建立连接(三次握手...),连接完成后建立了可靠的通道,就可以通过http请求数据打包发送给服务端,
2、服务端接收请求

 

posted @ 2020-04-30 17:27  小L要努力吖  阅读(872)  评论(0编辑  收藏  举报