网络基础之传输层--TCP协议和UDP协议

一、端口号

1、概念

端口号(Port)标识了一个主机上进行通信的不同的应⽤程序;程序的身份标识,不同的服务器有不同的端口号,传输层收到数据后根据端口号来确定需要把这个数据交给哪个端口号。不同的服务器要求的协议不同,应该按照正确的格式匹配。(HTTP的格式只能交给HTTP的服务器来处理。)

在TCP/IP协议中, 用 "源IP", "源端口号", "目的IP", "目的端口号", "协议号" 这样一个五元组来标识一个通信(可以通过netstat -n查看);
2、划分

(1)0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的. 

(2)1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.

知名端口号:也可以按照自己的方式来指定端口号,而不使用固定的端口号

 

有些服务器是非常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:

ssh服务器, 使用22端口

ftp服务器, 使用21端口 

telnet服务器, 使用23端⼝

http服务器, 使用80端⼝

https服务器, 使用443

65535为端口号的上限,超出65535会截断,对后期的端口号造成影响。

查看知名端口号(知名端口号需要root权限才能访问)

cat /etc/services

3、问题:

(1. 一个进程是否可以bind多个端口号? 

答:可以;因为一个进程可以有多个socket,每个socket绑定一个

(2. 一个端口号是否可以被多个进程bind?

答:不可以;两个进程分别去绑定一定会失败,一个进程绑定之后再去fork子进程则是可以的。

4、常见指令

(1)、 netstat

查看服务器的状态

(2)、pidof

查看进程ID:(1)ps aux | grep 进程名:可以获得除了进程id以外的其他一些信息

(2)pidof  进程名:只能获取进程id

二、UDP协议:

1、协议格式:(序列化之后的结果,本来就是一个结构化的数据,把结构化的数据放到字符串上,放到连续空间的数组上,不同字段的含义不同。)

 

 

a、16位UDP长度, 表示整个数据报(UDP首部+UDP数据)的最⼤⻓度; (一个UDP数据报的最大长度是65535也就是64k,传输的数据超过64k,那么一个UDP数据报不能存储得下,此时需要分包,手动把数据分成若干个能被UDP承载的大小,按照特定的顺序发送,接收端手动的对这些包进行顺序上的处理(因为包的接受顺序是不确定的)。通常不使用UDP传输一个比较大的数据。

b、如果校验和出错, 就会直接丢弃:校验和保证数据的准确性,采用CRC的方式在发送数据之前计算一个校验和,接收到数据之后再计算一个校验和,与传输过程中收到的校验和进行对比,如果校验和相等,则认为是正确的;如果不相等,数据一定是错误的。

UDP的特点

a、UDP传输的过程类似于寄信. 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接; 

b、不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;

c、面向数据报: 不能够灵活的控制读写数据的次数和数量;(应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并;)【用UDP传输100个字节的数据: 如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接收100 个字节; 而不能循环调用10次recvfrom, 每次接收10个字节】

注意

首部中表示长度的数据为2个节字,64k,非常有限。一旦发送的数据超过最大限制,就要进行分包。分包是要通过程序员手动写代码实现(实现数据控制),比较麻烦

基于UDP的应用层协议:

NFS: 网络文件系统 

TFTP: 简单文件传输协议 

DHCP: 动态主机配置协议 (同一个主机,联网则分配,不连网则不分配,IP地址会变,这个协议一般放在路由器上)(进行IP地址分配的过程中,由于现在IP地址都是IPV4版本,只能表示42亿9千万个字节,所以IP地址的数量是有限的,为了缓解IP地址不够用的问题,采用动态主机配置)

BOOTP: 启动协议(用于无盘设备启动) 

DNS: 域名解析协议(IP地址的另一种表示方法,有IP地址才能找到接收端。根据域名映射成IP地址,通过域名解析协议实现)

 也包括你自己写UDP程序时自定义的应用层协议

三、TCP协议:可靠的基础上保持传输速率尽可能高

1、TCP的报文格式(TCP和UDP对应得位置完全对等,TCP协议头中得字段比UDP协议头中的字段要多)

 

a、16位源端口号,16位目的端口号

b、32位序号:表示这句话是什么话(接收端在应答的时候必须指明应答的是哪一条请求,32位序表示发送的数据的序号是什么)

c、32位确认序号:现在在应答哪句话序号与确认序号不一定同时存在(若是发送的数据是动态访问数据的报文,可能没有确认序号,只有32位序号,表示“我是谁”。若是发送是应答报文,不需要去进行具体传输,可能就只有确认序号,而没有序号。)

d、4位首部长度:4位表示的最大长度为15个字节乘以4即60个字节,报头的最大长度位60个字节,和数据长度没有任何关系

保留(6位):现在不使用,说不准以后需要使用

e、6个标志位如下,标志了数据报的类型

URG:

ACK:确认报文,为1:32位确认序号有效,表示确认报文。

PSH:

RST:

SYN:为1表示为一个同步报文段,建立TCP连接

FIN:客户端断开连接,置1为结束报文段,主动发起断开连接的请求

f、16位窗口大小:一次性传输多少数据

g、16位校验和:收到数据的时候重新计算一遍校验和并与收到的校验和进行对比,结果不同,则出现问题;(校验数据是否有效)

h、16位紧急指针

i、选项:变长的字段,选项有很多种,并且可以同时具有多个选项,这些选项用一定的规则排列好。如果没有选项,选项部分为0个字节选项也可以有若干个,但是总的协议头长度不会超过60个字节。最大长度是60 ,不能大于60,但是可以小于60.

2、TCP协议中的连接管理机制

在正常情况下, TCP要经过三次握⼿手建⽴立连接, 四次挥⼿手断开连接

 

三次握手建立连接的过程:客户端尝试和服务器端建立连接,发送一个SYN报文段,服务器已经绑定好了端口并且已经listen完成,服务器端收到SYN报文段之后,会立刻响应一个ACK,并且服务器也尝试和客户端建立连接,也发送一个SYN报文段。一个TCP建立连接的过程由内核完成,客户端建立连接是调用的connect函数,调用connect的瞬间内核会给对端服务器发送FIN,此时connect还在执行、没有返回。服务器端收到SYN本质上是网卡收到SYN,然后交给网络驱动程序,驱动程序交给内核,内核把数据交给TCP的相关模块,然后TCP模块决策返回SYN,这个过程和代码没有关系。确认连接的过程由内核完成。调用connect函数时触发了内核的一些逻辑,由内核(TCP模块包含在内核之中)完成三次握手。客户端connect返回之后即完成了三次握手。服务器端收到ACK之后accept才能返回,accept是把内核中建立好的连接拿到代码之中,连接建立好之前accept处于挂起状态。所以三次握手之后accept才能返回,用new_socket与客户端联系。

a、TIME_WAIT状态:

 

 

 

使用捎带应答,当要发送ACK的时候,等待一会儿,正好和FIN一起发送回去,就将四次挥手变成了三次。

确认应答机制:
(1)应答接受到的数据;
(2)应答收到了哪一个数据
所以需要对报文进行编号,即序列号(TCP发送数据,所有的数据都相当于是在缓冲区中发送,缓冲区就是一个内存或者说是一个数组,可以把序列号看作若干个数组,数组中有若干个字节,以每一个字节的下标作为序列号(以字节为单位进行编号)

a、TCP序列号即表示该报文从第n个字节开始发送
b、TCP报文头中并没有数据的长度。起始这个长度是由IP协议协助表示的。(可以结合IP数据报的报头)
超时重传机制:
(1)、数据没传送到接收端就发生了丢包
发送端发送的数据发生了丢包,超时重传机制就是把已发送的未接收到的数据重新发送一遍。超时重传机制是TCP的一部分,是由内核实现的(TCP模块是内核的一部分),调用write或者send函数把数据放到内核缓冲区中,内核缓冲区中考虑是否重传、何时重传,和用户的代码没有关系,简化了编程的难度。保证收到ACK过一段时间进行重传。(为了减少重传的开销,减小重传的频率,超时重传的时间,取决于编译器。不同的编译器,选择不同。连续多次重传都超时,说明网络已经断开,恢复不了,断开连接,但是此时的断开连接是异常断开TCP的链接,不能使用四次挥手。)
(2)、接收端收到了消息,但是ACK丢失了。(比如qq产生的bug,发送消息时显示没发送出去,但是对方接收到了消息。)此时,发送端并不知道数据是在还没发送到接收端时(原始数据)丢失的,还是接收端响应(ACK)之后,没有接收到响应信息。此时,发送端,只要到达一定时间,ACK没有回来,就重传一份。,但是此时相当于接收端同一个数据接收了两份。此时接收端需要进行去重(接收端接收到的数据先放到内核之中,内核中有一个接收缓冲区,数据发送过来,先放到内核的接收缓冲区之中,缓冲区中的数据还没有就绪,不能通过代码反映出来当内核认为数据准备就绪之后才允许read函数把数据取出来。接收方会在内核缓冲区里对数据进行去重。)(接收端通过序列号判断判断是否重复,序列号相同,则重复)。
超时的时间如何确定? 【超时重传机制,第二次重传的时间应该比第一次重传的时间长】
a、最理想的情况下, 找到一个最小的时间, 保证 "确认应答一定能在这个时间内返回".
b、但是这个时间的长短, 随着网络环境的不同, 是有差异的
c、如果超时时间设的太长, 会影响整体的重传效率
d、如果超时时间设的太短, 有可能会频繁发送重复的包
【达到一定的重传次数,则认为连接失败】
TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间
a、Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的 超时时间都是500ms的整数倍
b、如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传
c、如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.
d、累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接
2、滑动窗口【帮助我们进一步提高传输效率】:
(1), 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个 数据段. 这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候.[很长的时间都用在了等待ACK返回上面】
(2)一次批量发送,批量收取【把一次发送一条的等待时间压缩到了一起,利用一份等待时间同时等了多分数据,等待时间变短,传输效率变高了。】
a、窗口大小指的是无需等待确认应答(ACK)而可以继续发送数据的最大值【一次可以批量发送的数据】.
b、发送前n个段(即第一批数据)的时候, 不需要等待任何ACK, 直接发送
c、收到第一个ACK后, 滑动窗口向后移动, 继续发送第n+1个段的数据; 依次类推
d、操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答; 只 有确认应答过的数据, 才能从缓冲区删掉
e、窗口越大, 则网络的吞吐率就越高
【一次批量发的数据越多,等待的时间越少,但是同时要求接收缓冲区的空间越大。若是一次发送的数据过大,速度过快,可能出现接收端处理不过来的情况。】
 批量发送的过程中出现了丢包:
a、传输的数据包丢失【快速重传】(滑动窗口下的一个重传机制,重传效率很高,没有重发多余的数据,只是重发了丢失的数据)
数据包丢失,则对方没收到,由于序列号发生了丢包,又因为接收端的主机返回的ACK里面的数据为下一个响应的应答的ACK,则反复向发送端发送“自己需要的是丢包的范围内的数据”,重复若干次之后,发送端会重传一个刚刚丢失的数据,而后续的没有发生丢包的数据不用重传,因为其余数据都存放在缓冲区中。缓冲区中的数据可以拿出来接着使用。

b、返回的ACK丢失
因为是批量发送,即使第一个数据发生了丢包,第二个数据还是发送出去了,他们是同时发送的。
此时发生了丢包,没有影响,虽然1001丢失了,但是接收到了2001的响应(说明1到2000我们都已经接收到了),下面的数据涵盖了前面的。因为ACK应答的序列号说,序列号之前的所有字节都已经确认收到了。若干个ACK,只要能收到一个ACK,则说明前面的都收到了,少发一些ACK可以节省系统开销,又对系统没有影响。

 

 3、流量控制:接收方根据缓冲区的承受能力决定发送方的发送速率。
窗口越大,传输速率越快,需要开辟更多的缓冲区来保存数据。发送方窗口设置多大,是受到接收方的处理速度的影响的,接收方返回的ACK中会包含缓冲区空余空间有多大,设置窗口大小的时候依据缓冲区的空间做决策。
a、接收端将自己可以接收的缓冲区大小放入 TCP ⾸首部中的 "窗口大小" 字段, 通过ACK端通知发送端;
b、窗口大小字段越大, 说明网络的吞吐量越高;
c、接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
d、发送端接受到这个窗口之后, 就会减慢自己的发送速度;
e、如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 接收端不返回ACK,但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.(需要知道缓冲区的剩余空间,剩余空间中有多少,则发送多少;因为缓冲区存不下会发生丢包)
4、拥塞控制:刚开时传送数据的时候,网络状态时拥堵还是流畅是不确定的,先以较慢的速度发送一会儿,如果没有问题,则逐步加快(指数上升), 然后(此时采用线性增长),快到的一定程度会丢包。又从最小的地方开始

拥塞窗口:拥塞窗口和流量控制窗口中较小的值,是发送端实际发送的滑动窗口。谁小谁生效。共同控制发送端的发送速率。

A、延时应答:让接收端的ACK不立即返回,稍等一会儿再返回,给接收端留下一个处理数据的时间。延迟应答有一定的限制
B、捎带应答:再延迟应答的基础上,ACK稍等一会儿再发,服务器和客户端是一问一答的形式。可以在服务器返回应答的过程中,顺便把上一条数据的ACK捎带回去。相当于把要发送的两个数据合二为一。

大概的过程:

 

3、粘包问题:那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的 应用层数据包.
方式1:用特殊的符号把字符串划分成自己想要的几个部分,显示分隔符
方式2:标记出包的长度,显示包的长度
UDP不会出现粘包问题,发送数据和接收数据是对称的(一次发送一个完整的数据报,一次就读出一个完整的数据报)。而TCP是面向字节流的,不需要一次性将数据读完,这种机制就可能导致反而读不完一个完整的数据。管道也是面向字节流的,也存在粘包问题,只要是面向字节流,就有可能发生粘包问题。
4.TCP的异常处理:
(1)进程的终止:
A、进程异常终止:进程终止,而且进程终止的一瞬间关闭文件描述符,和调用close函数是相同的。
(2)机器重启:
A、正常重启:重启之前会把所有的进程都强制结束掉,和进程终止(四次挥手)情况相同。
(3)机器掉电和网线断开:
机器掉电(断网)和重启不同,掉电进程来不及关闭文件描述符,没有进行四次挥手,就结束了。对端感知不到机器掉电(断网):a、对
端尝试写数据时,发现写不成功,才能发现连接已经不存在了(超时重传),尝试重新进行三次握手,重新建立连接。由于断电,重新连接也会发生失败。b、等待对方写数据,TCP内置了一个保活定时器,会定时询问对方是否还在(即使对方没有发数据,也给对方发送一个简短的数据询问对方是否还存在)。【保活定时器发送的数据叫做心跳包】
5、对于TCP的认知
TCP既要保证可靠性,同时又尽可能的提高性能 ;
可靠性:
校验和(检验是否正确);序列号(保证数据按序到达);确认应答(可靠性的基础);超时重发(丢包后进行的操作);连接管理;流量控制(防止数据传输太快而引起的丢包);拥塞控制(防止数据传输太快而引起的丢包)
提高性能:
滑动窗口(提高性能的核心);快速重传(滑动窗口下丢包的处理方式);延迟应答(让数据窗口尽可能大);捎带应答(能够把多条数据合并为一条)
定时器(超时重传定时器;保活定时器;TIME_WAIT定时器)
6、基于TCP的应用层协议:
HTTP;HTTPS;SSH;Telnet(网络传输中的常用工具,基于TCP进行可靠性传输);FTP(文件传输);SMTP(传输邮件常用的协议);还有自定制协议
7、TCP与UDP的对比:
(1)TCP用于可靠传输,对数据传输的可靠性有严格要求时使用TCP;
(2)UDP不需要创建连接,不需要应答,速率比TCP高,适用于高速传输或者对实时性要求比较高的,但是UDP对大小有限制。
(3)UDP可以用于广播,而TCP不可以(一个数据可以同时发给多个人);
 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuruhua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值