【Linux】网络编程基础包含TCP详解

网络结构模式

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地址通常采用"点分十进制"表示。

端口

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

端口分类:

  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 参考模型或七层模型。 它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。

在这里插入图片描述
应用层: 网络服务与最终用户的一个接口。这一层为用户的应用程序(例如电子邮件、文件传输和 终端仿真) 提供网络服务。

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

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

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

网络层: 进行逻辑地址寻址,在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。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地址是标识网络中不同主机的地址,而端口号就是同一台主机上标识的不同进程的地址。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校验码。

类型:0x800表示IP、Ox806表示ARP、0x835表示 RARP

ARP协议

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

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

请求ARP是ip类型,以太网是ARP类型;应答ip,ARP

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

在这里插入图片描述

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

IP数据报格式

在这里插入图片描述
4位版本号:IPv4或者IPv6

4位头部长度(单位为4字节):一行有4个字节,假设不算选项,则有5行。则一排(其实协议整体都是一行,只不过为了排版方便才分成这么多行形成了一个表)是20个字节,而头部长度仅为4位,2的4次方最多可以表示到15,是没办法表示20个字节的。所以就设了头部长度的每一位的单位是4个字节。这样4位头部长度最多可以表示60个字节,所以除了必选的20个字节,选项也就是最多40个字节。

8位服务类型:一般不用,取值为0

总长度:首部加上数据的总长度,单位为字节

TTL:源主机为数据报设定的一个生存时间,每经过一个路由器就减1,如果减到0就表示路由已经太长了仍然找不到目的主机的网络,就丢弃该包,因此这个生存时间是跳(hop)。

8位协议:协议字段指示上层协议是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:传输控制协议,面向连接的,可靠的,基于字节流,仅支持单播传输

在这里插入图片描述

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标志位置为1
    2.生成一个随机的32位的序号seq=J ,这个序号后边是可以携带数据(数据的大小)
第二次握手:
    1.服务器端接收客户端的连接:ACK=1
    2.服务器会回发一个确认序号: ack=客户端的序号+数据长度(上图中假设传输数据为0,仅SYN占据了一个字节)+SYN/FIN(按一个字节算)
    3.服务器端会向客户端发起连接请求: SYN=1
    4.服务器会生成一个随机序号:seq =K
第三次握手:
    1.客户单应答服务器的连接请求:ACK=1
    2.客户端回复收到了服务器端的数据:ack=服务端的序号+数据长度+SYN/FIN(按一个字节算)

seq为序号,ack为确认序号。仅当SYN=1的时候,序号seq才有用。同理,仅当ACK=1的时候,确认序号ack才有用。

为什么是3次握手呢?

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

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

2MSL(Maximum Segment Lifetime)
主动断开连接的乙方,最后会进入一个TIME_WAIT的状态,这个状态会持续:2msl

  • msl:官方建议:两分钟,实际是30s,2msl就是60s

当TCP连接主动关闭方接收到被动关闭方发送的FIN和最终的ACK后,连接的主动关闭方必须处于TIME_WAIT状态并持续2MSL时间。

这样就能够让TCP连接的主动关闭方在它发送的ACK丢失的情况下重新发送最终的ACK(因为在被动关闭方发送了FIN但没有收到主动关闭方发送的ACK后,被动关闭方又会重传FIN,使主动关闭方再次发送ACK)。
主动关闭方重新发送的最终ACK并不是因为被动关闭方重传了ACK(它们并不消耗序列号,被动关闭方也不会重传),而是因为被动关闭方重传了它的FIN。事实上,被动关闭方总是重传FIN直到它收到一个最终的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可用状态

在这里插入图片描述

问题:为什么四次挥手中服务器端的ACK和FIN不同时发送,而是分开发送?
答:因为只是客户端想要断开连接,也许此时服务器端还不想断开连接,可能还有一些数据需要向客户端发送。所以需要分开发送

问题:如果超过了2msl的时间,被动关闭方还是没有接收到ACK(也就是第四次挥手丢失),会怎么样?
答:主动方收到被动方重发的FIN报文,2msl重新计时。服务端(被动关闭方)重发 FIN 报文的次数由tcp_orphan_retries 参数控制,重传次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,直接进入到 close 状态。

问题:三次握手和四次挥手分别丢失,会发生什么》
答:TCP 三次握手和四次挥手,中间失败了会发生什么?

问题:为什么四次挥手中的第一次挥手有ACK呢?
答:发送一个FIN的同时还需要带一个ACK,这个ACK是为了确认被动关闭方所发送的上一条数据的。ACK : TCP协议规定,只有ACK=1时表示对方数据发送有效,也规定连接建立后所有发送的报文的ACK必须为1。可参考这篇文献:四次挥手中你还不知道的ACK机制

半关闭

当TCP链接中A向B发送FIN请求关闭,另一端B回应ACK之后(A端进入FIN_WAIT_2状态),并没有立即发送FIN给A,A方处于半连接状态(半开关),此时A可以接收B发送的数据,但是A已经不能再向B发送数据。

从程序的角度,可以使用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的读写功能

端口复用

端口复用最常见的用途:

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

常用查看网络相关信息的命令:
netstat
    参数:
        -a 所有的socket
        -p 显示正在使用的socket的程序的名称
        -n 直接使用IP地址,而不通过域名服务器

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

  1. 如果有多个进程共享一个套接字,close每被调用一次,计数就减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放
  2. 在多进程中如果一个进程调用了shutdown(sockfd,SHUT_RDWR),其他进程将无法进行通信,但如果一个进程调用了close(sockfd)将不会影响到其他进程

做一个测试:
1、首先启动server,接着查看网络相关信息,运行结果如下:
在这里插入图片描述

协议为tcp,ip地址为0.0.0.0,端口号为9999,状态为LSTEN,server为应用程序的名称

2、接着继续启动客户端
在这里插入图片描述
第一个是专门用来监听的socket。下面两个显示的就是服务端和客户端建立的连接,因为建立链接要两个套接字socket,所以就是两个。

3、接着我用Ctrl+C终止服务器端
在这里插入图片描述
此时可以看到,因为服务器端已经关闭,甚至连名称都不在显示,但因为客户端没有主动发起关闭,所以服务器端的状态处于FIN_WAIT2。客户端则是处于等待关闭的状态。

接下来等待一段时间,不进行任何操作,会发现服务端信息没有了
在这里插入图片描述
4、再次启动服务器端,(老师视频里是bind报错了,是想证明此时127.0.0.1:9999这个端口还处于FIN_WAIT2,此端口还未被释放,因此造成了不便报错,从而引出端口复用)我用的是ubuntu20.04,当再次启动服务器时,如下图,它又在0.0.0.0上分配了一个端口,所以就没报错
在这里插入图片描述
4、此时,我先关闭服务器端,再关闭客户端,按老师的应该是下图这样(6666应该是9999,这里用下别人的图
在这里插入图片描述
此时也就要等TIME_WAIT的时间过去,也就是1分钟,接着这个端口被释放掉就又可以用了。立即启动服务器端则会出错。

端口复用函数

#include<sys/types.h>

#include<sys/socket.h>
//设置套接字的属性(不仅仅能设置端口复用)
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
参数:
	-sockfd:要操作的文件描述符
	-level:级别 - SOL_SOCKET(端口复用的级别)
	-optname:选项的名称
		-SO_REUSEADDR
		-SO_REUSEPORT
	- optval:端口复用的值(整形)
		- 1:要复用端口
		- 0:不要复用端口
	- optlen:optval参数的大小

端口复用,设置的时机是在服务器绑定端口之前。
setsockopt();
bind();

猜你喜欢

转载自blog.csdn.net/mhyasadj/article/details/131121358
今日推荐