C++实战项目-网络编程基础包含TCP详解

目录

网络结构模式(网络应用程序设计模式)

C/S结构

B/S结构

 MAC地址

IP地址

子网掩码 

端口

网络模型

通信过程

数据包封装

协议 

以太网帧格式

ARP数据报格式

IP数据报格式

UDP协议格式

 TCP协议格式

封装 

分用

TCP详解

TCP与UDP

TCP通信流程

TCP 三次握手

TCP 滑动窗口(TCP流量控制)

TCP 四次挥手

TCP 状态转换

半关闭

2MSL

端口复用

点到点,端到端

 路由器和交换机的区别


网络结构模式(网络应用程序设计模式)

C/S结构

        客户机-服务器(client-server)结构。服务器完成对数据的管理,客户机完成与用户的交互任务。客户端是因特网上访问别人信息的机器,服务器是提供信息供人访问的机器。

        客户端通过局域网与服务器相连,接受用户请求,并通过网络向服务器端提出请求,对数据库进行操作。服务器接受客户机的请求,将数据提交给客户机,客户机将数据进行计算并将结果呈现给用户。服务器还要提供完善安全保护及对数据完整性的处理等操作,并允许多个客户机同时访问服务器,这就对服务器的硬件处理数据能力提出了很高的要求。

        在C/S结构中,应用程序分为两部分:服务器部分和客户机部分。

        服务器部分是多个用户共享的信息与功能,执行后台服务,如控制数据库的操作

        客户机部分为用户所专有,负责执行前台功能,如出错提示、数据计算等

优点:

        1.协议选用灵活

        2.客户端响应快(能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后再提交给服务器)

        3.操作界面漂亮、形式多样。可以充分满足客户自身的个性化要求

        4.C/S结构的管理信息系统具有较强的事务处理能力,能够实现复杂的业务流程

        5.安全性较高,C/S一般面向相对固定的用户群,程序更加注重流程,它可以对权限进行多层次校验,提供了更安全的存取模式,对信息安全的控制能力很强,一般高度机密的信息系统采用C/S结构适宜。

缺点:

        1.客户端需要安装专门的客户端软件。首先涉及到安装的工作量,其次任何一台电脑出问题(病毒、硬件损坏)都需要进行安装或维护。软件升级时,每一台客户机需要重新安装,其维护和升级成本高。

        2.对客户机的操作系统一般也有限制,不能够跨平台

B/S结构

        B/S结构(浏览器、服务器模式)是web兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用,客户机上只要安装一个浏览器,服务器安装数据库(MySQL、Oracle)。浏览器通过Web Server同数据库进行数据交互。

优点:

        B/S架构最大的优点是总体拥有成本低、维护方便、分布性强、开发简单,可以不用安装任何专门的软件就能实现任何地方进行操作,客户端零维护,系统的扩展性非常容易,只需要一台能上网的电脑

缺点:

        1.通信开销大,系统和数据的安全性较难保障

        2.个性特点明显降低,无法实现具体有个性化的功能要求

        3.协议固定:http/https

        4.客户端服务器的交互式请求-响应模式,通常动态刷新页面,响应速度明显降低

 MAC地址

网卡式一块被设计用来允许计算机在计算机网络上进行通讯的计算机硬件,又称为网络适配器或网络接口卡NIC。其拥有MAC地址,属于OSI模型的第2层,它使得用户可以通过电缆或无线相互连接。每一个网卡都有一个被称为MAC地址的独一无二的48位串行号。网卡的主要功能:1.数据的封装与解封装 2.链路管理 3数据编码与译码

MAC地址,也称为局域网地址、以太网地址、物理地址或硬件地址,它是一个用来确认网络设备位置的地址,由网络设备制造商生产烧录在网卡中。在OSI模型中,第三层网络层负责IP地址,第二层数据链路层负责MAC地址MAC地址用于在网络中唯一标识一个网卡、一台设备若有一或多个网卡,则每一个网卡都需要并会有一个唯一的MAC地址。 

MAC地址长度位48位(6个字节),通常表示为12个16进制数。如:00-16-EA-AE-3C-40就是一个MAC地址,其中前3个字节,16进制数00-16-EA代表网络硬件制造商的编号,它由IEEE分配,而后3个字节,16进制数AE-3C-40代表制造商所制造的某个网络产品的系列号。只要不更改自己的MAC地址,MAC地址在世界是唯一的。形象的说,MAC地址就如同身份证号码一样,具有唯一性。

IP地址

IP协议是为了计算机网络相互连接进行通信而设计的协议。在因特网中,它是能连接到网络的所有计算机网络实现互相通信的一套规则,规定了计算机在因特网上进行通信时应当遵循的规则。

IP协议实际上是一套由软件程序组成的协议软件,它把各种不同“帧”统一转换成“IP数据报”格式,这种转换时因特网的一个最重要的特点,使所有各种计算机都能在因特网上实现互通。正是因为有了IP协议,因特网才得以迅速发展成为世界上最大、开放的计算机通信网络。因此,IP协议也可以叫做"因特网协议"。

IP地址是指互联网协议地址(又称网际协议地址)。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异

IP地址是一个32位的二进制数,通常被分割位4个8位二进制数。IP地址通常采用"点分十进制"表示。

IP地址编址方式

        为了方便寻址和层次化构造网络,每一个IP地址包括两个标识码(ID),即网络ID和主机ID。同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包括服务器、路由器等)有一个主机ID与其对应。

        A类IP地址

        一个 A 类 IP 地址是指, 在 IP 地址的四段号码中,第一段号码为网络号码,剩下的三段号码为本地计算 机的号码。如果用二进制表示 IP 地址的话,A 类 IP 地址就由 1 字节的网络地址和 3 字节主机地址组 成,网络地址的最高位必须是“0”。A 类 IP 地址中网络的标识长度为 8 位,主机标识的长度为 24 位,A 类网络地址数量较少,有 126 个网络,每个网络可以容纳主机数达 1600 多万台。 A 类 IP 地址 地址范围 1.0.0.1 - 126.255.255.254(二进制表示为:00000001 00000000 00000000 00000001 - 01111111 11111111 11111111 11111110)。最后一个是广播地址。 A 类 IP 地址的子网掩码为 255.0.0.0,每个网络支持的最大主机数为 256 的 3 次方 - 2 = 16777214 台。

        B类IP地址

         一个 B 类 IP 地址是指,在 IP 地址的四段号码中,前两段号码为网络号码。如果用二进制表示 IP 地址的 话,B 类 IP 地址就由 2 字节的网络地址和 2 字节主机地址组成,网络地址的最高位必须是“10”。B 类 IP 地址中网络的标识长度为 16 位,主机标识的长度为 16 位,B 类网络地址适用于中等规模的网络,有 16384 个网络,每个网络所能容纳的计算机数为 6 万多台。 B 类 IP 地址地址范围 128.0.0.1 - 191.255.255.254 (二进制表示为:10000000 00000000 00000000 00000001 - 10111111 11111111 11111111 11111110)。 最后一个是广播地址。 B 类 IP 地址的子网掩码为 255.255.0.0,每个网络支持的最大主机数为 256 的 2 次方 - 2 = 65534 台。

        C类IP地址

        一个 C 类 IP 地址是指,在 IP 地址的四段号码中,前三段号码为网络号码,剩下的一段号码为本地计算 机的号码。如果用二进制表示 IP 地址的话,C 类 IP 地址就由 3 字节的网络地址和 1 字节主机地址组 成,网络地址的最高位必须是“110”。C 类 IP 地址中网络的标识长度为 24 位,主机标识的长度为 8 位, C 类网络地址数量较多,有 209 万余个网络。适用于小规模的局域网络,每个网络最多只能包含254台 计算机。 C 类 IP 地址范围 192.0.0.1-223.255.255.254 (二进制表示为: 11000000 00000000 00000000 00000001 - 11011111 11111111 11111111 11111110)。 C类IP地址的子网掩码为 255.255.255.0,每个网络支持的最大主机数为 256 - 2 = 254 台。

        D类IP地址

        D 类 IP 地址在历史上被叫做多播地址(multicast address),即组播地址。在以太网中,多播地址命 名了一组应该在这个网络中应用接收到一个分组的站点。多播地址的最高位必须是 “1110”,范围从 224.0.0.0 - 239.255.255.255

         特殊的网址

        每一个字节都为 0 的地址( “0.0.0.0” )对应于当前主机; IP 地址中的每一个字节都为 1 的 IP 地址( “255.255.255.255” )是当前子网的广播地址; IP 地址中凡是以 “11110” 开头的 E 类 IP 地址都保留用于将来和实验使用。 IP地址中不能以十进制 “127” 作为开头,该类地址中数字 127.0.0.1 到 127.255.255.255 用于回路测 试,如:127.0.0.1可以代表本机IP地址。

子网掩码 

        子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个 IP 地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合 IP 地址一起使用。子网掩码只有一个作用,就是将某个 IP 地址划分成网络地址和 主机地址两部分。 子网掩码是一个 32 位地址,用于屏蔽 IP 地址的一部分以区别网络标识和主机标识,并说明该 IP 地址是在局域网上,还是在广域网上

         子网掩码是在 IPv4 地址资源紧缺的背景下为了解决 lP 地址分配而产生的虚拟 lP 技术,通过子网掩码将 A、B、C 三类地址划分为若干子网,从而显著提高了 IP 地址的分配效率,有效解决了 IP 地址资源紧张 的局面。另一方面,在企业内网中为了更好地管理网络,网管人员也利用子网掩码的作用,人为地将一 个较大的企业内部网络划分为更多个小规模的子网,再利用三层交换机的路由功能实现子网互联,从而 有效解决了网络广播风暴和网络病毒等诸多网络管理方面的问题。

端口

端口是绑定每一个进程的,或者说服务器通过这个端口进行监听是否有客户端与之连接。

端口分类:

1.周知端口

        周知端口是众多周知的端口号(又称知名端口、公认端口或者常用端口),范围0-1023,他们紧密绑定于一些特定的服务。【80端口用于分配给WWW服务、21端口用于分配给FTP服务、23端口分配给Telnet等

        网络服务是可以使用其他端口号的,如果不是默认的端口号则应该在地址栏上指定端口号,方法是在地址栏里输入“网址:端口号”。但一些系统协议使用固定端口号,它是不能被改变的,比如139端口专门用于NetBIOS与TCP/IP之间的通信,不能手动改变

2.注册端口

        端口号从1024到49151,他们松散地绑定于一些服务,分配给用户进程或应用程序,这些进程主要是用户选择安装的一些应用程序。这些端口在没有被服务器资源占用的时候,可以用用户端动态选择位源端口。【我们之间写程序时可选用的端口

3.动态端口/私有端口

        动态端口的范围从49152到65535。称之为动态端口,是因为它一般不固定分配某种服务,而是动态分配。

网络模型

OSI七层模型

        七层模型,亦称 OSI(Open System Interconnection)参考模型,即开放式系统互联。参考模型 是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为 OSI 参考模型或七层模型。 它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。

应用层 为应用程序提供服务
表示层 数据格式转换、数据加密
会话层 建立、管理和维护会话
传输层 建立、管理和维护端到端的连接
网络层 IP选址和路由选择
数据链路层 提供介质访问和链路管理
物理层 物理设备的标准
        应用层:网络服务与最终用户的一个接口。这一层为用户的应用程序(例如电子邮件、文件传输和 终端仿真) 提供网络服务

        表示层:数据的表示、安全、压缩。主要是进行对接收的数据进行解释、加密与解密、压缩与解压 缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。

        会话层通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求。

        传输层:定义了一些传输数据的协议和端口号。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这 一层数据叫做段。

        网络层:进行逻辑地址寻址,在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。

        数据链路层建立逻辑连接、进行硬件地址寻址、差错校验等功能。定义了如何让格式化数据以帧为单位进行传输,以及如何让控制对物理介质的访问。将比特组合成字节进而组合成帧,用MAC地 址访问介质。

        物理层主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为 1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。

TCP/IP四层模型

        现在Internet使用的主流协议族是TCP/IP协议族,它是一个分层、多协议的通信体系。TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层、网络层、传输层和应用层。每一个层完成不同的功能,且通过若干协议来完成,上层协议使用下层协议提供的服务。     

 应用层:应用层是TCP/IP协议的第一层,是直接为应用进程提供服务的

                (1)对不同种类的应用程序他们会根据自己的需要来使用应用层的不同协议

                     (邮件传输协议:SMTP  万维网应用:HTTP  远层登录服务:TELNET)

                (2)加密、解密、格式化数据(将计算机能看懂的东西变成人能看懂的)

                (3)建立或解除与其他节点的联系,这样可以充分节省网络资源

传输层:定义了一些传输数据的协议和端口号。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这 一层数据叫做段。

网络层:可以进行网络连接的建立和终止以及IP地址的寻找等功能

网络接口层:由于兼并了物理层和数据链路层所以网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的路线。

通信过程

两台计算机通过TCP/IP协议通讯的过程:

 上图表示两台计算机在同一个网段中的情况,如果两台计算机在不同的网段中。那么数据从一台计算机到另一台计算机传输中要经过一个或多个路由器。

         链路层有以太网、令牌环网等标准,链路层负责网卡设备的驱动、帧同步(即从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。交换机是工作在链路层的网络设备,可以在不同的链路层网络之间转发数据帧,由于不同链路层的帧格式不同,交换机要将进来的数据包拆掉链路层首部重新封装之后再转发。

        网络层的IP协议是构成Internet的基础。Internet上的主机通过IP地址来标识,Internet上有大量的路由器负责根据IP地址选择合适的路径转发数据包,数据包从Internet上的源主机到目的主机往往需要经过十多个路由器。路由器是工作在第三层的网络设备,同时兼有交换机的功能,可以在不同的链路层接口之间转发数据包,因此路由器需要将进来的数据包拆掉网络层和数据链路层两层首部并重新封装。IP协议不保证传输的可能性,数据包在传输过程中可能丢失,可靠性在上层协议或应用程序中提供支持。

        网络层负责点到点的传输(主机或路由器),传输层负责端到端的传输(源主机和目的主机)。传输层可选择TCP或UDP协议。

        TCP是一种面向连接的、可靠的协议,有点像打电话,双方拿起电话互通身份之后就建立了连接,然后说话就行了,这边说话保证那边可以听得到,并且按说话的顺序听到的,说完话挂机断开连接。也就是说TCP传输的双方需要首先建立连接,之后由TCP协议保证数据收发的可靠性,丢失的数据报自动重发,上层应用程序收到的总是可靠的数据流,通讯之后关闭连接。

        UDP是无连接的传输协议,不保证可靠性,有点像寄信,信写好了放到邮箱,既不能保证信件在邮递过程中不会丢失,也不能保证信件寄送顺序。使用UDP协议的应用程序需要主机完成丢包重发、消息排列等工作。

        目的主机收到数据包后,如果经过各层协议栈最后到达应用程序呢?

以太网驱动程序首先根据以太网首部的“上层协议”字段确定该数据的有效载荷(除去协议首部传输的数据)是IP、ARP、RARP协议的数据报,然后交给相应的协议处理。假如是IP数据报、IP协议再根据首部的“上层协议”字段确定该数据报的有效载荷是TCP、UDP、ICMP还是IGMP,然后交给相应的协议处理。假如是TCP或UDP段,TCP或UDP再根据TCP首部或UDP首部的“端口号”字段确定应该将应用层数据交给哪个用户进程。【分用】

        IP地址是标识网络中不同主机的地址,而端口号就是同一台主机上标识的不同进程的地址。IP地址和端口号合起来标识网络中唯一的进程。

        虽然IP、ARP、RARP数据报都需要以太网驱动程序来封装成帧,但是从功能上划分,ARP和RARP属于链路层,IP属于网络层。虽然TCP、UDP、ICMP、IGMP的数据都需要IP协议来封装数据报,但是从功能上划分,ICMP和IGMP与IP同属于网络层,TCP和UDP属于传输层。

数据包封装

        不同的协议层对数据包有不同的称谓。在传输层叫做段,在网络层叫做数据报,在链路层叫做帧。数据封装成帧后发送到传输介质上,到达目的的主机后每层协议再剥掉相应的首部,最后将应用层数据交给程序应用。 

协议 

 网络协议简称协议,是通信计算机双方必须共同遵循的一组约定。包括如何建立连接、怎样互相识别等。只要遵守这个约定,计算机之间才能互相通信交流。

三要素:语法、语义、时序

为了使数据再网络上从源到达目的,网络通信的参与方必须遵循相同的规则,这套规则称为协议,它最终体现在网络上传输的数据包的格式

协议往往分成几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。

常见的协议:

应用层:FTP(文件传输协议)、HTTP(超文本传输协议)、NFS(网络文件系统)

传输层:TCP(传输控制协议)、UDP(用户数据报协议)

网络层:IP(因特网互联协议)、ICMP(因特网控制协议)、IGMP(因特网组管理协议)
网络接口层:ARP(地址解析协议)、RARP(反向地址解析协议)

以太网帧格式

 

其中目的地址和源地址是指网卡的硬件地址(MAC地址),长度48位,是在出厂时固化的。可以通过ifconfig命令查看。协议字段有三种值,分别对应IP、ARP、RARP。帧尾是CRC校验码。

以太网帧中的数据长度规定最小46字节,最大1500字节,ARP和RARP数据包的长度不够46字节,要在后面进行补充。最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU,如果一个数据包从以太网路由器到拨号链路上,数据包长度大于拨号链路MTU,则需要对数据包进行分片。【ifcong中可以看到】MTU这个概念指数据帧有效载荷的最大长度,不包括帧头长度。 

补充:TTL 表示最长生命周期 ,每跳一个单位(每经过一个路由器TTL-1)

提问:为什么不把以太网帧协议载荷变大(变得超级大)?

           因为如果发送的数据接受端没有接收到,要重发。显然重发1500比60000方便(快)。

ARP数据报格式

        在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号(提前告知的,在程序中包含的),却不知道目的主机的硬件地址,而数据包首先被网卡接受到再去处理上层协议,如果接受到的数据包的硬件地址与本机不符,则直接丢弃。因此在通讯前必须获得目的主机的硬件地址。ARP协议就起到这个作用。

每台主机的内核中都维护着一个ARP缓存表,源主机首先在主机的ARP表中查找目的主机的硬件地址,如果找到了就将数据包发送给对应的目的主机。如果没有,则源主机会广播一个ARP请求到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播)。目的主机接受到广播的ARP请求,发现其中的IP地址与本机的相符,则发送一个ARP应答数据包给源主机,并更新自己的ARP缓存表,将自己的硬件地址填写在应答包中。

        每台主机都维护着一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项过期时间一般为20分钟。

硬件类型:1表示MAC地址

协议类型:0x800表示IP地址 

硬件地址长度:6   (6*8 = 48)

协议地址长度:4   (4*8 = 32)

操作:1表示ARP请求    2表示ARP应答    3表示RARP请求   4表示RARP应答   

当是广播时:目的端以太网地址  FF:FF:FF:FF:FF:FF

IP数据报格式

IP数据报的首部长度和数据长度是可变长的,但总是4字节的整数倍。对于IPV4,4位版本字段是4。4位头部长度的数值是以4字节位单位的,最小值为5 ,也就是说首部长度最小值为4*5=20,也就是不带任何选项的IP首部,4位能表示的最大值是15,也就是说首部长度最大是60字节。8位TOS字段有3个位用来指定IP数据报的优先级(目前已经废弃),还要4个位表示可选的服务类型(最小延迟、最大吞吐、最大可靠性、最小成本),还有一个位总是0。

总长度是整个数据报的字节数(包括头部和数据)

每传一个IP数据报,16位的标识加1,可用于分片和重新组装数据报。

3位标志和13位偏移量用于分片。

TTL:源主机为数据报设定的一个生存时间,每经过一个路由器就减1,如果减到0就表示路由已经太长了仍然找不到目的主机的网络,就丢弃该包,因此这个生存时间是跳(hop)。协议字段指示上层协议是TCP、UDP、ICMP、IGMP。然后是校验和,只校验IP首部,数据的校验由更高层协议负责。

UDP协议格式

源端口号:发送方端口号

目的端口号:接收方端口号

长度:UDP用户数据报的长度,最小为8(仅含头部)

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

 TCP协议格式

 1.源端口号:发送方端口号

2.目的端口号:接收方端口号

3.序列号:本报文段的数据的第一个字节的序号

4.确认序号:期望收到对方下一个报文段的第一个数据字节的序号

5.首部长度(数据偏移):TCP报文段的数据起始处距离TCP报文段的起始处有多远,即首部长度。单位:32位

6.保留:占6位,保留今后使用,目前应置为0

7.紧急URG:此位置1,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送

8.确认ACK:仅当ACK=1时确认号字段才有效,TCP规定,在连接建立后所有传达的报文都必须把ACK置1

9.推送PSH:当两个应用进程进行交互式的通信时,有时在一端的应用进程希望子啊键入一个命令后立即能够收到对方响应。在这种情况下,TCP就可以使用推送操作,发送方TCP把PSH置1,并立即创建一个报文段发送出去,接收方收到PSH=1的报文段,就尽快交付给接收应用进程,而不再等到整个缓冲都填满后再向上交付

10.复位PST:用于复位相应的TCP连接

11.同步SYN:仅在三次握手建立TCP连接时才有效。当SYN=1而ACK=0时,表明这是一个连接请求报文段,对方若同意建立连接,则应在相应的报文段中使用SYN=1和ACK=1。SYN置1就表示这是一个连接请求或连接接受报文

封装 

应用程序数据在发送到物理网络之前,将沿着协议栈从上往下依次传递,每层协议都将在上层数据的基础上加上自己的头部信息(包括以太网帧的尾部CRC),以实现该层的功能,这个过程就称为封装 

分用

当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中的本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序。这个过程称为分用。分用时依靠头部信息中的类型字段实现的。

TCP详解

TCP与UDP

        TCP和UDP都是传输层的协议。

        UDP:用户数据报协议,面向无连接,可以单播、多播、广播,面向数据报,不可靠交付

        TCP:传输控制协议,面向连接的,可靠的,基于字节流,仅支持单播传输

UDP TCP
是否创建连接 无连接 面向连接
是否可靠 不可靠交付(丢包不重传) 可靠交付(丢包重传)
连接对象的个数 一对一、一对多、多对多 一对一
传输方式 面向数据报 面向字节流
首部开销 8个字节 最少20个字节
适用场景 实时应用(视频会议、直播) 可靠性高的应用(文件传输)

TCP通信流程

服务器端:

1.创建一个用于监听的套接字

        -监听:监听有客户端的连接

        -套接字:这个套接字其实就是一个文件描述符

2.将这个监听文件描述符和本地的IP和端口绑定(IP和端口就是服务器的地址信息)

        -客户端连接服务器的时候使用的就是这个IP和端口

3.设置监听,监听的fd开始工作

4.设置阻塞,当有客户端发起连接,解除阻塞。接受客户端的连接,会得到一个和客户端通信的套接字(fd)

5.通信

        -接受数据

        -发送数据

6.通信结束,断开连接

客户端:

1.创建一个用于通信的套接字(fd)

2.连接服务器,需要指定连接的服务器的 IP 和 端口

3.连接成功,客户端可以直接和服务器通信

        - 接收数据

        - 发送数据

4.通信结束,断开连接

TCP 三次握手

TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓“连接”,其实是客户端和服务器端内存里保持的一份关于对方的信息(IP地址、端口号)

TCP可以看作是一种字节流,他会处理IP层或以下的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放到TCP头部

TCP提供一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接、四次挥手来关闭一个连接。

 三次握手的过程:

        1.客户端发送一个带SYN标志的TCP报文到服务器。这个三次握手过程中的段1

          客户端发出段1,SYN位表示连请求。序号是0,这个序号在通信中用作临时地址,每发送一个书记字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包是情况。另外,规定SYN位和FIN位也要占一个序号,这次虽然没发数据,但是由发了SYN位,因此下次再发送应该用序号1001。mms表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大帧长度,就必须在IP层分片,为了避免这种情况,客户端声明自己的最大段尺寸,建议服务器端发来的段不要超过发来的段不要超过这个长度。

        2.服务器端回应一个带ACK和SYN标志的响应报文。它表示对刚才客户端SYN的回应,同时又发送SYN给客户端,询问客户端是否准备好进行数据通讯。这是三次握手中的第2个报文段。

        服务器发出段2,也带有SYN位,同时置ACK位表示确认,确认序号是1,表示“我接受到序号为0及以前所有的段,请你下次发送序号为1的段”,也就是应答了客户端的连接请求,同时也给客户端发出一个连接请求,同时声明最大尺寸为1024

        3.客户必须再次回应服务器端一个ACK报文。这个报文段2

        客户端发出段3,对服务器的连接请求进行应答,确认序号是8001。在这个过程中,客户端和服务器端分别给对方发了连接请求,有应答了对方的连接请求。在建立连接的同时,双方协商了一些信息。例如双方发送序号的初始值、最大段尺寸

为什么是3次握手呢?

通过3次握手才能够确定客户端的发送数据、数据数据的功能正常。服务器端的接收数据和发送数据正常。2次握手显然无法证明,比如客户端端发送SYN连接请求,服务器端回应ACK报文并发送,那么只能证明客户端发送数据正常,接收数据的能力不能确定。4次握手也可以达到,但是3次就能搞定,多花费一次没有必要。并且在三次握手的过程中,双方协商了一些信息,例如双方发送序号的初始值、最大段尺寸。

TCP 滑动窗口(TCP流量控制)

滑动窗口是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络拥挤情况直接发送数据。由于大家不知道网络拥挤状况,同时发送数据,导致中间节点阻塞丢包,谁也发送不了数据,所以就有了滑动窗口机制来解决此问题。滑动窗口协议是用来改善吞吐量的一种技术,即容许发送方在接收任何应答之前传送附加的包。接收方告诉发送方在某一时刻能送多少包(窗口尺寸)

还有一种情况,当发送端发送的速度较快,接收端收到数据后处理速度较慢,而接收缓冲区的大小是固定的(一般采用循环队列),就会丢失数据。TCP协议通过“滑动窗口”机制解决着一问题。

看上面的通讯过程:

     1.发送端(客户端)发起连接,声明最大尺寸是1460。初始序号是0,窗口大小4K,表示“我的接收缓冲区还有4K字节空闲区,你发送的数据不要超过4K”。接受端应答连接请求,声明最大段尺寸是1024,初始序号是8000,窗口大小是6K。发送端应答,三次握手结束。

     2.发送端发出段4-9,每一个段带1K的数据,发送端根据窗口大小知道接受端的缓冲区满了,因此停止发送数据。(6*1024=6K)

     3.接收端的应用程序处理了2K数据,接受缓冲区有2K空闲,接收发出段10,再应答已收到6K数据同时声明窗口大小为2K,并且包含了下一次发送的序号

     4.接收端的应用程序处理了2K数据,接收缓冲区有4K空闲,接收发出段11。重新声明窗口大小为4K.

     5.发送端发出段12-13,每一个段带1K数据,段13同时包含FIN位(FIN表示断开连接)

     6.接收端应答接收到2K数据(6145-8192),再加上FIN位占用一个序号8193,因此告知发送端下次发送从序号8194开始,连接处于半关闭状态,接收段同时声明窗口大小为2K

     7.接收端的应用程序处理了2K数据,接收端重新声明窗口大小为4K

     8.接收端的应用程序处理了2K数据,接收端重新声明窗口大小为6K

     9.接收端的应用程序处理全部数据后,决定关闭连接,发出段17,包含FIN位,发送端应答,连接完全关闭

        随着应用程序提走数据,虚线框不断向右滑动,因此称为滑动窗口

我们还可以分析出一个现象:

        应用程序所看到的数据是一个整体或者说是一个流,在底层通讯中这些数据可能被拆成数据包来发送,但是一个数据包有多少字节对应用程序是不可见的,因此TCP协议是面向字节流的协议,而UDP是面向消息的协议,每一个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的

TCP 四次挥手

        

         由于TCP是半双工的,因此每一个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向上的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将主动关闭,而另一方执行被动关闭。(发送数据跟发送请求应答不一样,一个定义在TCP头部(FIN、ACK、SYN),一个属于数据部分

     

        1.客户端发送FIN位表示关闭连接的请求

        2.服务器应答客户端的关闭连接请求 

        3.服务器处理完缓冲区中的数据后(做出了相应的应答),向客户端发送FIN表示关闭连接 

        4.客户端应答服务器的关闭连接请求

建立连接的过程是三次握手,而关闭连接通常需要4次挥手,服务器的应答和关闭连接请求通常不合并在一个段,因为有半关闭状态的情况(如上图,再者说A将需要的发送的数据发送完之后就调用close()关闭,B的缓冲区中还有数据没有处理完,还需要区应答A发送的数据,所以B的写端暂时不能关闭)。这种情况下客户端关闭连接之后就不能在发送数据给服务器端了,但是服务器端还可以发送数据给客户端,直到服务器也关闭连接为止。

TCP 状态转换

红线:客户端    绿线(虚线):服务器端   (两条线同步分析)

CLOSED:标识处于初始状态

LISTEN: 该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接

SYN_SENT:这个状态与STN_RCVD相呼应,当客户端SOCKET执行连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务器发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN请求

SYN_RCVD:该状态表示收到SYN报文,在正常情况下,这个状态时服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。此种状态时,当收到客户端的ACK报文后,会进入到ESTABLSHED状态(客户端和服务器端都是在接收到ACK进入ESTABLSHED状态)

ESTABLSHED:表示连接已经建立

FIN_WAIT_1:表示当处于ESTABLSHED状态时,想主动关闭连接的一方向对方发送FIN报文,此时该soceket进入FIN_WAIT_1状态(一般很快)

FIN_WAIT_2:主动关闭的一方,发出FIN收到ACK以后进入该状态。称之为半连接或半关闭状态。该状态下的soceket只能接受数据,不能发

TIME_WAIT:主动关闭的一方收到了对方的FIN报文,并发送出了ACK报文,等2MSL后即可回到CLOSED可用状态。为什么要设置2MSL? 确保最后一次发送的ACK对方能够接收到。如果丢失,则重新发送ACK

CLOSING:这种状态较特殊,属于一种比较罕见的状态。正常情况下,当你发送FIN报文后,按理先收到对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却收到了对方的FIN报文。(如果双方几乎同时close的话,那么就出现双方同时发送FIN的情况,也就进入CLOSING状态)

CLOSE_WAIT:此状态表示在等待关闭。当对方关闭一个SOCKET后发送FIN报文给自己,系统会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来察看是否还有数据需要发送给对方,如果没有则可以close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要关闭连接。

LAST_ACK:该状态是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,即可进入到CLOSED可用状态

补充说一下:socket本质是伪文件

半关闭

        当TCP连接中主动发送FIN请求关闭的一端收到对方发送的ACK回应,并且对方没有发送FIN之前,主动关闭的一方进入FIN_WAIT_2状态(半关闭状态),主动关闭的一端只能读不能写。

        

 使用close():说是半关闭,但不能读也不能写。这种状态不是正真的半关闭状态,所以使用shutdown()

使用close终止一个连接,但它只是减少了描述符的引用计数,并不是直接关闭连接,只有当描述符的引用计数为0时才关闭连接。shutdown不考虑描述符的应用计数,直接关闭描述符。也可以选择中止一个方向的连接,只中止读或只中止写。

        从程序的角度,可以使用API来控制实现半连接状态(主动实现半关闭状态)

        #include <sys/socket.h>

        int shutdown(int sockfd,int how);

        socket:需要关闭的socket的描述符

        how:   

                 SHUT_ED(0):  关闭sockfd上的读功能,此选项将不允许sockfd进行读操作

                 该套接字不再接受数据,任何当前在套接字接受缓冲区的数据将被无声的丢弃掉

                SHUT_WR(1):  关闭sockfd上的写功能,此选项将不允许socked进行写操作。

                                        进程不能对此套接字发出写操作。

                SHUT_RDWR(2):关闭sockfd的读写功能

      如果有多个进程共享一个套接字,close每被调用一次,计数就减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放

        在多进程中如果一个进程调用了shutdown(sockfd,SHUT_RDWR),其他进程将无法进行通信,但如果一个进程调用了close(sockfd)将不会影响到其他进程  

2MSL

TIME_WAIT状态的存在理由:

1.让4次握手关闭流程更加可靠,4次握手的最后一个ACK是由主动关闭方发送出去的,若这个ACK丢失,被动方会再次发送一个FIN过来,若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。

2.防止lost duplicate对后续新建正常链接的传输造成破坏。lost duplicate在实际的网络中非常常见,经常是由路由器产生故障,路径无法收敛,导致一个package在路由器A,B,C之间做类似死循环的跳转。(TCP超时重传、TCP是流式的,所有包到达的顺序是不一致的,TCP通过序号来拼接,通过2MSL TIME_WAIT状态,确保所有的lost duplicate都会消失掉,避免对新连接造成错误)

为什么设计在主动关闭的一方:

1.发最后ACK的是主动关闭的一方

2.只要一方保持TIME_WAIT状态,就能避免incarnation connection在2MSL内重新建立,不需要两方都有

RFC 793中规定MSL为2分钟,实际应用中常是30秒

程序设计中的问题

做一个测试,首先启动server,然后启动client,用Ctrl-C终止server,马上再运行server,运行结果:

 这是因为,虽然server的应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监听同样的server端口。我们用netstat命令查看一下:

 server终止时,socket描述符会自动关闭并发FIN段给client,client收到FIN后处于CLOSE_WAIT状态,但是client并没有终止,也没有关闭socket描述符,因此不会发FIN给server,因此server的TCP连接处于FIN_WAIT2状态。

现在用Ctrl-C把client也终止掉,再观察现象:

 client终止时自动关闭socket描述符,server的TCP连接收到client发的FIN段后处于TIME_WAIT状态。TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态,因为我们先Ctrl-C终止了server,所以server是主动关闭连接的一方,在TIME_WAIT期间仍然不能再次监听同样的server端口

端口复用

端口复用最常见的用途:

  • 防止服务器重启时之前绑定的端口还未释放
  • 程序突然退出而系统没有释放端口

        在server的TCP连接没有完全断开之前不允许重新监听是不合理的。因为,TCP连接没有完全断开指的是connfd(127.0.0.1:6666)没有完全断开,而我们重新监听的是lis-tenfd(0.0.0.0:6666),虽然是占用同一个端口,但IP地址不同,connfd对应的是与某个客户端通讯的一个具体的IP地址,而listenfd对应的是wildcard address。解决这个问题的方法是使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP地址不同的多个socket描述符。

#include<sys/types.h>

#include<sys/socket.h>

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

        setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP地址不同的多个socket描述符。

在server代码的socket()和bind()调用之间插入如下代码:

    int opt = 1;

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

点到点,端到端

 路由器和交换机的区别

 路由器和交换机的区别:交换机主要是实现大家通过一根网线上网,但是大家上网是分别拨号的,各自使用自己的宽带,大家各自上网没有影响,哪怕其他人在下载,对自己上网也没有影响,并且所有使用同一条交换机的电脑都是在同一个局域网内。路由器比交换机多了一个虚拟拨号功能,通过同一台路由器上网的电脑是共用一个宽带账号,大家之间上网是相互影响的,比如一台电脑在下载,那么同一个路由器上的其他电脑会很明显的感觉到网速很慢。同一台路由器上的电脑也是在一个局域网内的。

交换机工作在中继层,交换机根据MAC地址寻址,路由器工作在网络层,根据IP地址寻址,路由器可以处理TCP/IP协议,而交换机不可以。  

猜你喜欢

转载自blog.csdn.net/weixin_46120107/article/details/126446175