端口号(Port)标识了一个主机上进行通信的不同的应用程序;
在TCP/IP协议中,
通过 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信。
额外要注意的是一个端口只能bind一个进程,然后一个进程可以bind多个端口号。
进程就像是人,端口号就像是手机,一个手机只能被一个人用来通信,然后一个人却可以同时使用多个手机及进行通信。
注意 平时写程序使用端口时候要避开这些知名端口好,一面发生冲突。
该命令用于查看知名端口号
cat /etc/services
Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP
数据包的方法。
源端端口 | 对端端口 |
---|---|
数据报长度 | 校验和 |
数据 | 数据 |
格式解析
无连接,不可靠,面向数据报
其他特性:
发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因。而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据, 这一点和TCP是很不同的。怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方send一条信息的时候,无论底层怎样分段分片,TCP协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。
我们注意到, UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首 部). 如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。
当然, 也包括你自己写UDP程序时自定义的应用层协议;
面向连接,可靠传输,面向字节流。
面向连接意味着服务端与客户端双方建立连接之后才可以进行通信,这就像是打电话一样必须电话通了才可以进行交流。tcp有自己的连接管理,下面对tcp的连接管理进行解析。
由于tcp是面向连接的,因此收发数据前必须双方建立连接才可以。tcp建立连接的过程叫做三次握手。过程如下:
经过上面的三次信息的接收与发送之后,利用tcp通信的双方就建立好了可靠稳定的连接。
TIP: 为什么要三次握手而不是两次或者四次?
简单来说就是两次不安全,四次太多余。
两次就能建立连接,如果客户端发送多次SYN则都会建立连接浪费资源
如果客户端发送连接之后退出,服务端的新建套接字就会占用资源(保活机制)
也是因为tcp是面向连接的,因此断开连接也需要双方都确定断开才可以,不然的话就会有数据丢失等一系列的危险。tcp断开连接的过程叫做四次挥手。过程如下:
注意
前两次挥手"既让服务器端知道了客户端想要释放连接,也让客户端知道了服务器端了解了自己想要释放连接的请求。于是,可以确认关闭客户端到服务器端方向上的连接了。
后“两次挥手”既让客户端知道了服务器端准备好释放连接了,也让服务器端知道了客户端了解了自己准备好释放连接了。于是,可以确认关闭服务器端到客户端方向上的连接了,由此完成“四次挥手”。
TIP
为什么挥手是四次而不是三次?
FIN请求代表不再写数据,就是不再发送数据,而不代表不在接收数据了, 只有两边都FIN之后才代表两边可以断开连接了,类似于管道全部关闭写端,读完数据后返回一样。
TIME_WAIT的意义?
当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。
MSL指的是Maximum Segment Lifetime:一段TCP报文在传输过程中的最大生命周期。
2MSL即是服务器端发出为FIN报文和客户端发出的ACK确认报文所能保持有效的最大时长。
服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文;
如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;
否则客户端在2MSL内没有再次收到来自服务器端的FIN报文,说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。
TIP
为什么存在大量wait状态的套接字?为什么存在大量close_wait状态的套接字?
tcp通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端回向客户端发送一个保活探测数据报,要求客户端回复,若来凝结多次没有收到响应,则认为连接断开。
以下数据均为默认数据,通过设置套接字选项可配置 socketopt
可靠传输简单来说就是数据可以安全到达对面保证数据成功接收。
主要从是从下面几方面实现:
我们以一次完整的数据通信来对上面的机制进行讲解。
seq 本条数据的起始序号
ack 对方发送数据的确认序号,告诉对方收到了数据
注意 ack确认序号与ACK确认回复标志位使两个概念。下面用大小写进行区分
上面的过程可以分成两个小过程,
基于上面的性质, 我们可以很容易理解确认应答机制和超时重传机制。
确认应答机制的实现就是当发送端没有收到接收方的ACK确认回复的时候,那么就认为接收方没有收到这条数据,等到一定时间以后,超时重传机制就会重新发送这条数据。
通过ack与seq的确认,就可以实现数据的有序交付
在接受方的缓冲取会根据数据的seq来对数据进行排序,保证数据有序交付。
例子 :
主要阐述两个问题
下面对如何解决这两个问题进行说明。
TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间数据传输。每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。
发送窗口表示一次最多可以向接收方发送多少数据,窗口大小不能超过接收缓冲区大小。
接收窗口表示还可以最多一次接收多少数据。
缓冲区就像是一个循环队列,数据按序接收之后,先进先出。前沿和后沿只是一个序号并不是内存单元的编号。
TIP:
==滑动窗口机制允许发送方根据窗口大小以及MSS大小来连续发送多条数据。==同时也制定了多条协议来进行数据丢失的处理。下面列举几种。
拥塞控制解决的当网络较差的时候,发送数据过多导致的数据重传问题。
拥塞控制通过网络探测来确定当前是否可以发送多条数据,他是用一种慢启动快增长的方式来进行数据传输。简单来说就是,每次开始发送数据的时候,
(举例说明)
第一次发送1条数据,收到回复,此时验证网络良好。
第二次发送2条数据,收到回复,此时验证网络良好。
第三次发送4条数据,收到回复,此时验证网络良好。
第四次发送8条数据,其中有两条没有收到回复,此时验证网络不好。 那么下次重新从1开始。
第五次发送1条数据,收到回复,此时验证网络良好。
第六次发送2条数据,收到回复,此时验证网络良好。
网络良好时,发送数据的大小并不能无限增长,最大不能超滑动窗口大小,滑动窗口的大小是一个阈值。
概念
发送端连续发送多条数据,但是接收端接收到的不是后沿数据,认为后沿数据丢失,不会向发送方进行确认回复,然后会进行三次间隔的重传请求。
发送方收到三次请求后会向接收方重新传输该条数据。
问题
为什么要进行三次间隔重传请求?
避免网络原因导致的数据延迟到达。若数据在三次请求期间到达了,则接收方没有收到三次完整的请求,不用重传。
快速重传协议的优点?
避免发送端的超时重传,提高效率。
概念
接收方接收数据之后,并不立即进行确认回复,而是等待一段时间之后在回复。
优点
在接收方等待的这一段时间内,如果缓冲区的数据被取走了,那么窗口大小不会减小,甚至可能增大,发送方就可以发送更大的数据了。
概念
接收方接受数据之后,进行确认回复,在即将发送的数据头部中进行上一条数据的确认回复。
优点
确认回复就是在报头中修改确认序号,进行回复,使用捎带应答可以减少一个空的报头的响应占据带宽。
tcp是一种字节流传输服务 - 面向连接的,有序的一种最小以字节为传输单元的传输服务。
为什么说tcp可以以字节为传输单元呢?
发送端send发送数据的时候, 并不会将数据直接进行发送,而是先将数据放到发送缓冲区中,选择合适的时候从缓冲区中取出合适大小的数据进行封装发送。
接收端recv接收数据的时候, 并不会一条一条的向上交付,而是会将接收到的数据放到接收缓冲区中取出指定长度的数据进行交付。
优点:
传输灵活,大量小数据可以合并成一整条数据进行交付,减少io次数,接收方可以根据需要进行数据的取出。
缺点:
tcp交付的数据可能不是一条数据,而是多条数据混合的,导致上层按照一条数据进行处理,需要解决这种粘包问题。
以http和udp解决粘包问题进行说明
http头部以\r\n\r\n表示结束并在头部中通过content-length定义了正文的长度
udp在传输层中解决的,头部定长八个字节,头部中定义了数据报文长度。
netstat是一个用来查看网络状态的重要工具.
语法:netstat [选项]
功能:查看网络状态
n 拒绝显示别名,能显示数字的全部转化成数字
l 仅列出有在 Listen (监听) 的服務状态
p 显示建立相关链接的程序名
t (tcp)仅显示tcp相关选项
u (udp)仅显示udp相关选项
a (all)显示所有选项
在查看服务器的进程id时非常方便.
语法:pidof [进程名]
功能:通过进程名查看进程id
进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
机器重启: 和进程终止的情况相同.
机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即
使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ断线之后, 也会定期尝试重新连接
TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;
UDP用于对高速传输和实时性要求较高的通信领域, 例如, 早期的QQ, 视频传输等. 另外UDP可以用于广
播;