一、端口号
传输层是负责端对端之间的传输,端指的是端口(port);端口号(Port)标识了一个主机上进行通信的不同的应用程序。TCP协议和UDP协议都是传输层的协议。
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” (协议号指出此数据报所携带的是数据是使用何种协议,以便目的主机的IP层知道将数据部分上交给哪个处理过程。也就是协议字段告诉IP层应当如何交付数据。)这样一个五元组来标识一个通信(可以通过netstat -n查看);
1.1. 端口号范围划分
- 0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的。
- 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。
1.2. 认识知名端口号(Well-Know Port Number)
有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号。
- ssh服务器, 使用22端口。ssh是一种网络协议,用于计算机之间的加密登录。
- ftp服务器, 使用21端口。用于在 网络 上进行文件传输的一套标准协议。
- telnet服务器, 使用23端口。常用的远程控制Web服务器的方法。
- http服务器, 使用80端口。超文本传输协议,是互联网上应用最为广泛的一种网络协议。
- https服务器, 使用443端口号。HTTPS 协议是由 HTTP 加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议。
执行下面的命令, 可以看到知名端口号,我们自己写一个程序使用端口号时, 要避开这些知名端口号。执行下面的命令查看系统配置文件, 可以看到知名端口号。cat /etc/services :
一个进程是可以bind多个端口号,但一个端口号不可以bind多个进程。
1.3. netstat
netstat是一个用来查看网络状态的重要工具。 常用选项如下:
- n:进制使用域名解析功能。链接以数字形式展示(IP地址),而不是通过主机名或域名形式展示。
- l:listening,显示所有监听的端口。
- p:显示建立相关链接的程序名。
- a:显示所有链接和监听端口。
- u:(udp)仅显示udp相关选项。
- t:(tcp)仅显示tcp相关选项。
查看io情况:
1.4. pidof
在查看服务器的进程id时非常方便. 语法:pidof [进程名] 功能:通过进程名, 查看进程id
二、长短链接
2.1. 为什么需要长链接
短链接:一次链接只可以发送一次请求,和进行一次响应。 长链接:建立一次链接,释放一次,可以进行多次请求和响应。
在早期HTTP协议之中,只有短链接的方式,因为那时候需要传输的资源内容不多,比较简单,比如常见的网页。现在一张网页动不动就是几十上百长图片外加一大堆的文件内容,这些内容不可能一次性全部传输完毕,是需要分批进行传输的。
链接本身是有成本的,具体体现在空间和时间方面。
如果是短链接,则需要多次链接和断开连接过程(三次握手、四次挥手),如此一来就比较浪费资源。
如果使用长链接,则只需要建立一次链接,期间可以发起多次请求和响应,全部发送和接收完成后,最后断开链接。极大程度减少了建立链接的消耗,提高了数据传输的效率。
注意: HTTP属于应用层,应用层的职责范围不包括“链接”,也就是说长短链接并不是HTTP建立的。这里的长短链接指的是TCP链接。HTTP通过首部字段来和服务器协商TCP建立什么链接。
2.2. 客户端和服务器如何协商长短链接
2.3. 怎么区分多个请求
三、UDP协议
3.1. 协议格式
- 16位源端口:数据从哪一个端口发出来的,也就是数据从哪一个进程发送出来的。
- 16位目的端口:数据想要到哪一个端口去,也就是数据想要去往哪一个进程。
- 16位UDP长度:表示整个数据报(UDP头部+UDP数据)的最大长度。因此UDP长度减去头部长度(8字节),就是有效载荷(数据)的长度。(注意: 在实际中还要减去IP20字节的报头,因为IP的总长度也是16位,如果不减交付给IP时就会溢出)。
- 16位的UDP校验和:校验数据在传输过程中是否失真,数据在传输的过程中需要经过很多链路设备,如果在转发过程中有某个字节损坏,就相当于整个这个数据失真了,如果UDP接收方校验和出错,就会直接将数据丢弃掉,且不会通知发送方。 这是UDP不可靠的原因之一。
如何通过端口号找到进程(将有效载荷交付给上层)
内核通过哈希算法,根据对应的映射关系,找到端口对应的进程。
每个UDP报文的有效载荷最大是多少?
65507约等于64K。
为什么最大是65507?
因为UDP包头有2个byte用于记录包体长度,2个byte可表示最大值为:2^16-1=64K-1=65535(字节),UDP报头占8字节, IP报头占20字节,65535-28 = 65507。
为什么要多减去IP报头的20字节,而不是单纯地减去UDP报头的8字节?
因为UDP是要作为数据交给下层(网络层)的IP的,在IP报文中,IP的总长度也是16位(最大为65535字节),而这其中包括UDP的数据(65507字节)和IP的报头(20字节),如果UDP的数据多于65507字节,IP报文就会溢出。
我们可以通过UDP套接字来进行测试,当sendto失败时,返回值为-1:
3.2. UDP的特点
-
无连接:知道对端的 IP和端口号就直接进行传输,不需要建立链接,至于对方是否收到消息,UDP不管。 -
不可靠:没有确认和重传机制,如果发生丢包,数据无法到达对方,UDP协议也不会给应用层返回任何错误消息。 -
面向数据包:不能够灵活的控制读写数据的次数和数据,每次读取数据要么一次性读完,要么不读。
1.为什么会有可靠性问题?
网络传输中线路越长、干扰越多,对数据产生的影响就越大。
2.不可靠在那些情况?
丢包、乱序、接收缓冲区满了(丢包)。
3.3. UDP的缓冲区
-
UDP没有真正意义上的发送缓冲区,调用sendto会直接拷贝给内核,由内核将数据传给网络层协议,进行后续的传输动作。 -
UDP具有接收缓冲区,但是这个接受缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序是一致的(顺序也是可靠性的一种),如果缓冲区满了,在到达的UDP数据就会丢失(丢失了不会再重复发送)。 -
UDP的socket即能读也能写,是全双工的。
3.4. UDP使用注意事项
我们注意到, UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含8字节的UDP首部)。 然而64K在当今的互联网环境下, 是一个非常小的数字。如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。
3.5. 基于UDP的上层协议
3.6. 16位的UDP校验和的校验原理
目的:检测UDP段在传输中是否发生错误(如比特翻转)
- 失真了 : udp协议就会将该udp数据报丢弃
- 没有失真:当应用层调用recvfrom函数的时候,就会将udp数据报给到应用层
发送方:
- 将UDP头部除了校验和以外的内容处理为16比特整数序列。(16位源端口号、16位目的端口号、16位UDP长度)
- 对这三个16比特整数序列进行求和,当求和遇见溢出的时候,进行回卷
- 然后将最终结果取反。得到的结果放在 UDP 报文段中的检验和字段。
回卷:当进行 16 比特的加法运算的时候,如果进位到 17位,则将第 17 位和后 16 位进行加法和运算。
接收方:
- 将UDP头部的内容处理为16比特整数序列。(16位源端口号、16位目的端口号、16位UDP长度、16位UDP校验和)。
- 4个的16比特整数序列(包含了校验和)加在一起(求和溢出时进行回卷),没有差错的话,就是 1111 1111 1111 1111,此时校验成功。
- 如果校验成功,会将数据交给应用层;如果校验失败,即使数据已经到达了接收方传输层的UDP协议,也会被丢弃。数据有可能在传输的过程中失真。
|