计算机网络---传输层(tcpudp)
Posted Moua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机网络---传输层(tcpudp)相关的知识,希望对你有一定的参考价值。
目录
一、再谈端口号
端口号用来唯一标识一台主机上通信的进程,在tcp协议中用“源ip”、“源端口”、“目的IP”、“目的端口”、“协议号”这样一个五元组来标识一个通信。
1、端口号范围划分
- 0 - 1023: 知名端口号 , HTTP, FTP, SSH 等这些广为使用的应用层协议 , 他们的端口号都是固定的 .
-
1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.
一些知名端口号:
- ssh服务器使用22号端口号;
- ftp服务器使用21号端口号
- telnet使用23号端口号
- http使用80端口号
- https使用443端口号
2、相关指令
1)查看知名端口号
cat /etc/services
2)netstat查看网络状况
netstat选项
- n:拒绝显示别名,能显示数字的全部转化成数字。
- l:列出所有在listen服务状态
- p:显示建立相关链接的程序名
- t:只显示tcp相关选项
- u:只显示udp相关选项
- a:显示所有选项,默认不显示listen相关
3)查看服务器的进程id--pidof
pidof 进程名
思考1:一个进程可以bind多个端口号?
可以,一个进程可以绑定多个端口号,通过这些端口号都可以找到这个进程。
思考2:一个端口号可以被多个进程bind?
不可以,端口号的作用是唯一标识一台主机上的具体某一个进程,如果多个进程都绑定一个端口号就失去了端口号的意义。
二、UDP协议
用户数据报协议(udp)是工作在传输层的一个重要协议,UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
1、udp协议格式
思考1:上层协议是如何将udp协议的报头和有效载荷(数据)分离?
udp的报头是一个8字节的定长报头,当拿到一个udp数据报是读取到的前8个字节就是报头,报头中包含一个16位的udp长度字段,通过该字段计算出udp有效载荷大小。这样就将udp报头和有效载荷成功分离。
思考2:udp协议最多可以传送多少数据?
注意:16位udp长度可以认为是一个unsigned类型,且16位udp长度包括报头的8字节。
16位udp长度最多可以表示65535个字节,而报头占8字节,因此udp有效载荷最大长度为65535-8=65527字节。
思考3:udp协议如何保证用户数据报的完整性?
udp称为用户数据报协议,因此一定要保证用户数据报的完整性,具体做法就是8字节报头+16位udp长度来计算有效载荷长度,从而确保上层协议拿到的是一个完整的数据报。
思考4:16位检验和有什么作用?
udp是一个无连接不可靠的传输层协议,它的检验和只是用来检验数据本身是否出错。由于udp的不可靠性,一旦检测到检验和出错,udp协议直接将该数据包丢弃。
总结:udp协议通过协议包头中的16位的源端口和16位的目的端口知道自己“从哪来,到哪去”,通过16位udp长度知道自己携带了多大的数据报,并且可以通过这16位udp长度将报头和有效载荷进行分离。还有一个16位的检验和,用来验证数据报是否出错,如果出错直接丢弃。
2、udp的特点
udp协议有以下三个主要特点:
- 无连接:知道对端的IP地址和端口号就可以直接进行传输,不需要建立连接。
- 不可靠:没有确认机制,没有重传机制。如果因为网络原因导致数据丢失等,udp协议层也不给应用层返回任何信息。
- 面向数据报:传输的数据的单位是数据报。
- 由于udp是面向数据报的,就导致udp不能灵活的控制数据的传输和接收次数,udp交给应用层的报文udp就原样发送既不会拆分也不会合并。也就是说,应用层交给udp100个字节的数据,udp一次就传输100个字节的数据,接收端也必须一次接收完100个字节的数据。
其次udp还有以下特点:
- udp的socket是全双工的(同一时间既能读取数据也能写入数据)
- udp没有真正意义的发送缓冲区但是具有接收缓冲区。
udp的缓冲区:
udp是全双工的,同一时间可以同时进行读和写数据,但是如果数据量较大时就有可能导致数据处理不过来,因此需要缓冲区将数据存起来。
- udp没有真正意义的发送缓冲区,调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作
- udp具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 并且如果缓冲区满了, 再到达的UDP数据就会被丢弃。
4、udp使用注意事项及基于udp的应用层协议
udp可以传输的数据大小为2^16字节(64k),在当今的互联网环境下是一个非常小的数字,因此如果需要传送大于64k的数据就需要在应用层手动分包多次发送,并在接收端手动拼接。
基于udp的应用层协议:
- NFS: 网络文件系统
- TFTP: 简单文件传输协议
- DHCP: 动态主机配置协议
- BOOTP: 启动协议(用于无盘设备启动)
- DNS: 域名解析协议
三、TCP协议
TCP全称为传输控制协议,主要功能是对数据的传输进行详细的控制。
1、tcp协议格式
tcp协议的报头是不定长的,报头的首部有一个4位字段表示报头的长度,具体表示的是该tcp 报头有多少个32bit(4字节),也就是说规定了tcp报头最大长度为(2^4-1)*4 = 60字节。由于tcp传输的是字节流,因此tcp的有效载荷可以是任意长度的。
同样的,头部8个字节源端口和8个字节目的端口表示数据“从哪来到哪去”。由于tcp是面向连接的可靠传输,因此在tcp的头部还有很多字段用来确保数据的可靠传输(后面详细讲)。
2、tcp报头解释
- 源端口:表示发送数据的进程
- 目的端口:接收数据的进程
- 32位序号:发送的数据的序号
- 32位确认序号:接收到的数据的确认号(一般为序号+1)
- 4位首部长度:表示tcp首部长度(20~60字节)
- 6位标志位
URG:紧急指针是否有效
ACK:确认号是否有效
PSH:当接收端缓冲区满时,且一直没有拿走数据,发送端会发送一个PSH标志位为1的数据,提示接收端应用快速将缓冲区的数据取走。
PST:重新建立连接,携带PST标志位的报文称为复位报文段。
SYN:请求建立连接,携带SYN标志位的报文称为同步报文段。
FIN:关闭连接,携带FIN标志位的报文称为结束报文段。
- 16位窗口大小:接收端的缓冲区大小是有限的,给接收端发送数据将接收缓冲区填满后如果在继续发送,则会将原来的数据覆盖,因此tcp协议会将自己的接收缓冲区的剩余大小保存在16位窗口大小中和数据一起发送过去。需要注意的是,在tcp进行三次握手时就会进行第一次窗口大小的“协商”。
- 16位校验和:发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.
- 16位紧急指针:标识哪部分数据是紧急数据。
3、TCP确认应答机制
tcp进行的是可靠传输,传输的是字节流。因此,对于tcp协议需要做到以下两点:①确保接收端成功接收到数据②确保接收端接收到数据的有序性。
网络中存在许多复杂的情况,因此并不能保证接收端接收到的数据的顺序就是发送端发送的顺序,因此tcp协议需要确保接收端接收到数据后能够按照正确的顺序对数据进行处理。
确认应答机制:发送方每发送一个数据,接收方就要向发送方发送一个确认信号,表明自己已经收到该数据,从而确保接收端成功接收到数据。
思考:tcp 是如何实现确认应答机制并且确保接收到的数据的顺序的?
在tcp报头中,有两个4字节的字段,分别表示的是32位序号和32位确认序号。tcp协议对将每个字节的数据都进行了编号,这个编号就是序号。在发送数据时会将数据的编号放在报头的32位序号中一起发送过去,接收端接收到数据后会发送一个包含32位确认序号的数据,32位确认序号表示的意思是已经接收到序号为x的数据期望收到x+1号数据。例如,上图中发送端发送1~1000号数据,接收端接收到会给发送端发送确认号为1001的确认数据,表示自己已将将1000之前的所有数据都接收到了,希望下次接收到的是1001号数据。这样,tcp协议就完美的实现了确认应答机制。同时tcp协议还可以通过32位序号将接收到的序号按照发送顺序进行处理,保证数据的顺序不会出错。
注意:确认应答机制永远也不能对所有的数据进行确认,总是会有最后一条数据无法确认。因此确认应答机制并不对确认数据进行确认。
4、TCP超时重传机制
tcp协议在保证数据可靠传输时,还需要确保丢失的数据能够重新发送。因为,在主机A发送给主机B的数据可能由于网络原因导致数据发送失败,因此主机A也就收不到主机B的确认。在tcp协议中,如果主机A给主机B发送一个数据,在规定时间内主机A没有收到数据B的确认,主机A 就认为该数据丢失了(实际上不一定是丢失了,有可能是网络拥堵数据正在发送),会将该数据重新发送给主机B,这就是超时重传机制。
无论是数据发送失败(接收端确实没有接收到数据),还是数据还没发送过去或者只是确认数据发生丢包(接收端接收到了数据),一旦超时发送端都会将该数据重新进行发送,那么一定会导致接收端存在很多重复的数据,那么该如何设置超时时间呢?
最理想的情况就是找一个最小时间,确保数据在这个时间内一定能够到达。但是这个时间的长短随着网络环境的变化,是不同的。如果时间设置过长会影响传输速率,如果时间设置过短有可能会频繁发送重复的包。
TCP为了保证无论在任何情况下都能比较高性能的通信,会动态计算这个时间。在linux中超时时间以500ms为一个单位,每次判断超时重发的时间都是500ms的整数倍。如果重发一次仍然得不到应答,会等待500*2ms后进行重传,如果还是不能得到应答则在等待4*500ms重发,以此类推。当累计到一定次数,tcp会认为对端或者网络出现异常,直接强制断开连接。
5、tcp三次握手四次挥手
在正常情况下 , TCP 要经过三次握手建立连接 , 四次挥手断开连接。具体过程如下图:三次握手过程
1)如何理解连接
对于服务器来说,服务器是1对多的,一个服务器可能要被很多个客户端连接。因此,服务器端需要将众多的连接进行管理,这就导致服务器得为这些连接建立相应的数据结构,同时这些操作也是需要时间的。所以,建立连接是需要时间+空间代价的。
2)三次握手过程
- 一般情况下,第一次连接请求是由客户端主动发送的。
- 客户端向服务器发送一个SYN请求,并将自己置为SYN_SENT状态,阻塞等待服务器的应答。
- 服务器收到客户端的请求后,会向服务器端发送一个SYN+ACK数据包。表示服务器端收到客户端的请求,并且向客户端也发起连接请求。此时,服务器端变为SYN_RCVD,等待客户端的确认。
- 客户端收到服务器端的SYN+ACK数据包后会再次向服务器端发送一个ACK确认数据包,发送成功后客户端置为ESTABLISHED状态,并且认为已经连接成功。
- 当服务器端收到客户端的ACK确认后,此时双方建立连接成功,服务器置为ESTABLISHED状态。
3)为什么是三次握手?
- 如果是1次握手,客户端给服务器端发送一个连接请求直接就连接成功了,这与udp无连接有什么区别?建立连接是为了更好的管理,一次握手建立连接很容易遭到黑客的SYN洪水攻击,导致服务器宕机。
- 如果是2次握手,客户端向服务器端发送一个请求,服务器端向客户端发送一个确认,到此请求建立成功。那么存在一个问题,服务器端发送的ACK确认如果丢失了,此时服务器认为已经建立连接成功了,而客户端没有收到服务器的ACK确认认为没有建立连接成功,就会进行超时重传,这样就可能导致服务器端资源浪费,同时2次握手也容易遭到SYN洪水攻击。
- tcp传输数据时,最新的数据永远是无法保证可靠性的(最新的数据不会进行确认),当进行三次握手时,只要前两次失败客户端和服务器端就会认为连接没有建立成功。但是,如果第3三次握手失败,此时客户端认为建立成功了而服务器端认为没有建立成功,不会为其创建相应的数据结构,并且服务器端没有收到客户端的ACK确认就会进行超时重传,当重传次数达到一定程度后就直接强制断开连接,因此也不会对客户端造成很大的影响。但是,如果是四次连接就会导致服务器端认为连接建立成功,而客户端认为没有建立成功,此时浪费的是服务器资源,服务器是1对多的,如果大量的客户端对服务器连接都出现这种问题,就会给服务器带来巨大的资源浪费,甚至导致服务器崩溃。当然,五次握手和三次握手结果是相同的,但是三次握手是最小保证可靠连接的次数,相比于5/7...节省时间。
- 总结:为什么三次握手可以,第一个原因就是让服务器不要出现建立误判情况,浪费服务器资源;其次还有一个重要原因就是,以最小成本验证全双工(tcp是全双工的,三次握手就可以保证全双工通信信道的场通)。
四次挥手过程
1)为什么是四次挥手
断开连接是需要上双方同时建立起断开连接状态的,因此需要互相请求和确认,一共就是四次挥手。
2)四次挥手的过程
- 客户端向服务器端发送FIN断开连接请求,发送成功后客户端置为FIN_WAIT1状态。
- 服务器端收到客户端的FIN请求后,需要向客户端发送一个ACK确认。发送成功后,服务器端置为CLOS_WAIT状态。
- 客户端收到服务器端的ACK确认后进入FIN_WAIT2状态。
- 服务器端给客户端发送FIN断开连接请求,并进入ALST_ACK状态。
- 客户端向服务器端发送ACK确认,进入TIME_WAIT状态,此时客户端并没有立刻断开连接。
- 服务器端收到客户端的ACK确认后关闭连接,此时服务器端进入CLOSED状态,断开连接成功。
理解TIME_WAIT和CLOSE_WAIT状态
1)TIME_WAIT状态
为什么客户端给服务器端发完ACK确认后,没有立刻进入CLOSED状态?
对于客户端的最后一次ACK确认,服务器端不会在进行确认,如果客户端立刻进入CLOSED状态,有可能导致服务器端并没有接收到ACK确认,对FIN进行超时重传,但是此时客户端已经断开连接,服务器端是一直收不到客户端确认的,只能等到重传次数到达一定程度强制断开连接。因此,在客户端发送完确认后会等待一段时间,如果在该时间内没有收到服务器端重传的FIN数据就会断开连接,否则对重传的FIN重新进行确认,确保服务器端收到并断开连接。
其次,客户端发送完ACK确认进入TIME_WAIT状态,还有一个重要作用就是防止网络中没有传完,保证历史数据在网络中消散。
2)如何验证TIME_WAIT状态?
首先启动 server, 然后启动 client, 然后用 Ctrl-C 使 server 终止 , 这时马上再运行 server, 结果是绑定失败。这是因为 , 虽然 server 的应用程序终止了 , 但 TCP 协议层的连接并没有完全断开 , 因此不能再次监 听同样的 server 端口。 解决TIME_WAIT等待引起的绑定失败:setsockopt接口,即使㝉端口处于监听状态也可以进行绑定。
3)CLOSED_WAIT状态
首先屏蔽服务器端程序中关闭文件描述符的代码,启动服务器,让客户端进行链接,客户端连接成功后关掉客户端,此时客户端就向服务器端发送了断开连接的请求,但是由于服务器端屏蔽了close,无法断开连接。此时,查看服务器状态就为CLOSE_WAIT状态。
4)time_wait时间是多少比较合适呢?
2*MSL,msl表示数据从一端发送到另一端需要的最大时间,2MSL就是往返的最大时间。
总结:对于服务器上出现大量的 CLOSE_WAIT 状态 , 原因就是服务器没有正确的关闭 socket, 导致四次挥手没有正确完成. 这是一个 BUG. 只需要加上对应的 close 即可解决问题。6、滑动窗口
前面讨论的确认应答策略是基于“一次发送,一次确认”,经过“一次发送,一次确认”完成后才能进行下一次发送,这样数据的传输效率会很低。
但是,确认应答机制很好的保证了数据传输的安全性,为了解决其传输效率问题,又引入滑动窗口。滑动窗口是指,可以一次性发送一批数据,这一批数据发送的过程不需要等待其中某一个数据的确认,窗口大小就是指这批数据的最大值。
如下图:
- 发送前四个段时,不需要等待任何ACK,直接将四个段发送完。
- 收到第一个ACK后,滑动窗口向后移动继续发送接下来的四个段。以此类推
- 在上面这个图中,整个区域表示的是发送缓冲区。白色区域是滑动窗口
- 滑动窗口中的数据是已经发送等待确认的数据。
- 滑动窗口之前的数据是已经发送并且已经收到确认的数据。
- 滑动窗口之后部分的数据是还没有发送的数据
- 当接收到一个ACK时,滑动窗口的左边会右移。
- 当接收缓冲区(16位窗口大小)变大时,滑动窗口右边右移。因此,当滑动窗口越大时,表示对方的接收能变强。
- 滑动窗口大小除了受对方接收缓冲区剩余大小的影响,还跟拥塞控制有关(后边详细讲解)。因此,滑动窗口越大还表明网络状况好,网络吞吐率高。
新的技术的引入,必然会带来一些新的问题和挑战,滑动窗口虽然解决了数据传输效率低问题,那么如果数据丢包又该如何重传呢?
- 接收端收到了数据,但是接收端发送的ACK丢了。
其实,滑动窗口机制已经很好的解决了这个问题,滑动窗口中是可以容忍部分ACK丢包的,只要后续ACK进行确认即可(ACK确认序号表示的是该序号之前的所有数据都已经收到,接下来向收到的数据的序号)。例如,上图中1001的ACK丢了并不影响,只要后边任意一个到达都表示1~1000的收据已经收到。
- 数据报丢了,接收端,没有收到。
当数据包真正丢失了,是需要进行重传的,这也就要求滑动窗口中发送的ACK要确保他之前的数据都已经接收到。例如,接收端接收到的数据的顺序是1~1000、5001~6000、4001~5000,当接收到5001~6000的数据后不能立即发送6001的ACK,必须等到6001之前的数据全部到达才能发送。
其次,滑动窗口的重传机制和之前的超时重传机制也有所不同。滑动窗口中,如果某一个数据真的丢了(超过时间没有收到),接收方会给发送方发送的每一个不是丢失的数据发送的确认号都是丢失数据的确认号。当接收端接收到三次这个ACK时,会重新对这个ACK的数据进行重新发送。这种机制叫做高速重发机制,也称快重传。
例如:
- 当某一段报文段丢失之后 , 发送端会一直收到 1001 这样的 ACK, 就像是在提醒发送端 " 我想要的是 1001" 一样
- 如果发送端主机连续三次收到了同样一个 "1001" 这样的应答 , 就会将对应的数据 1001 - 2000 重新发送
- 这个时候接收端收到了 1001 之后 , 再次返回的 ACK 就是 7001 了 ( 因为 2001 - 7000) 接收端其实之前就已 经收到了, 被放到了接收端操作系统内核的接收缓冲区。
思考1:有了快重传,为什么还需要超时重传
其实,超时重传是一种兜底策略。试想,如果所发送的数据小于3次时,即使数据丢失也引发不了快重传,此时还是需要超时重传进行解决。同时,如果是最后一个数据丢了,也是无法引发快重传的。
7、流量控制
接收端处理数据的速度是有限的 . 如果发送端发的太快 , 导致接收端的缓冲区被打满 , 这个时候如果发送端继续发送 , 就会造成丢包, 继而引起丢包重传等等一系列连锁反应 . 因此TCP 支持根据接收端的处理能力 , 来决定发送端的发送速度 . 这个机制就叫做 流量控制 (Flow Control) ;- 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段, 通过ACK端通知发送端;
- 窗口大小字段越大, 说明网络的吞吐量越高;
- 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
- 发送端接受到这个窗口之后, 就会减慢自己的发送速度;
- 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.
注意:实际上接收端和发送端第一次“协商”窗口大小是在三次握手过程中。三次握手建立连接时,SYN包中就包含了窗口大小。
8、拥塞控制
虽然 TCP 有了滑动窗口这个大杀器 , 能够高效可靠的发送大量的数据 . 但是如果在刚开始阶段就发送大量的数据 , 仍然可能引发问题. 因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵 . 在不清楚当前网络状态下 , 贸然发送大量的数据 , 是很有可能引起雪上加霜的. TCP引入 慢启动 机制 , 先发少量的数据 , 探探路 , 摸清当前的网络拥堵状态 , 再决定按照多大的速度传输数据 ;为了解决这个问题,引入了拥塞窗口的概念。开始发送数据的时候,拥塞窗口定义为1,每收到一个ACK拥塞窗口+1,每次发送数据的时候将拥塞窗口和主机端反馈的窗口大小做比较,取最小的作为实际发送的窗口大小。
但是,这样的拥塞窗口增长速度是指数级别的。慢启动只是启动时速度慢,但是增长速度非常快。为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍. 此处引入一个叫做慢启动的阈值。当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长。
- 当TCP开始启动的时候, 慢启动阈值等于窗口最大值;
- 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;
9、延迟应答
如果接收端接收到数据就立即发送ACK确认,这时返回的窗口可能比较小,网络的吞吐率就低,传输效率也就降低了,同时有可能很快缓冲区的数据就会被取走,缓冲区变大。因此,接收端可以延迟一段时间在进行应答,从而提高网络吞吐率。
注意:窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;同时,延迟应答也不是每一个包都会延迟应答,会有数量(每隔几个包延迟应答一次)和时间(每隔多长时间延迟应答一次)限制。
10、捎带应答
在延迟应答的基础上,其实很多客户端、服务器都是“一发一收”的。捎带应答的意思就是说,接收端收到堆放的数据时,需要进行确认,同时接收端可能也有数据要交给对方,这时就可以将发送的数据和确认信息一起发送给对方。
10、tcp黏包问题
黏包问题是指,应用层发送一个数据包,传输层如果使用的是udp传输,那么该数据包会被分成一个个的报文进行发送,并且每个报文都有数据报长度这样一个字段来区分各个数据报。但是,如果传输层使用的是tcp,tcp传输的是字节流,在应用层看来其实就是一串字符,并且tcp协议中没有报文长度这样的标识,无法知道该报文的有效载荷长度,那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.
那么如何避免呢?对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可; 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置; 对于变长的包, 还可以在包和包之间使用明确的分隔符。
思考:udp是否会存在这个问题呢?
不会。首先,udp中有udp数据报长度字段可以区分数据报和数据报之间的边界问题。同时,udp是面向数据报的,也就是说一次要么发送一个完整的数据报,要么就不发。
11、tcp异常情况
- 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
- 机器重启: 和进程终止的情况相同(在重启前,电脑会提示还有正在运行的进程是否确认关闭,也就是说重启前会先关闭进程).
- 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放. 另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ 断线之后, 也会定期尝试重新连接.
四、TCP相关问题
1、再次理解什么是面向字节流
创建一个tcp套接字时,系统会为其创建相应的发送缓冲区和接收缓冲区。发送数据时,会先将应用层的用户数据保存在发送缓冲区中,如果缓冲区中的数据太少可以等一段时间在进行发送。如果发送的数据太多了,会被拆分成多个数据包发送出去。另一方面,tcp是全双工的,同一时间同一连接可以同时进行发送和接收数据。由于缓冲区的存在,tcp在发送数据时不必一次性将数据发完,例如:有1000个字节的数据,如果条件允许tcp可以一次发送完,也可以一次发送10个字节,发送100次。
2、基于TCP的应用层协议
- HTTP
- HTTPS
- SSH
- Telnet
- FTP
- SMTP
3、如何使用UDP实现可靠传输
udp是无连接、面向数据报、不可靠传输。要使用udp实现可靠传输就必须在它的上层(应用层)添加可靠性机制,例如:通过确认应答、超时重传、连接管理、流量控制、拥塞控制确保数据的可靠性,其次还可以通过滑动窗口、快速重传、延迟应答、捎带应答等机制提高效率。
4、理解Listen的第二个参数
Linux 内核协议栈为一个 tcp 连接管理使用两个队列 :- 半链接队列:用来保存处于SYN_SENT和SYN_RECV状态的请求(当全连接队列也满了是,如果在有用户连接就会加入到半连接队列中,半连接队列中允许有离开的连接)
- 全连接队列(accpetd队列):用来保存处于established状态,但是应用层没有调用accept取走的请求(当服务器负载过大时,如果还有客户端连接服务器就可以将它们暂时加入到全连接队列中,当服务器负载减小时在从全连接队列中取走)
5、分析TCP通信流程
在tcp的四次挥手过程中,由于捎带应答的存在,可能导致四次挥手变成三次挥手。也就是说,将第2/3次挥手同时发送过去。
6、TCP小节
实际上tcp在保证数据传输的可靠性的同时,还考虑了很多的效率问题:
可靠性:
- 检验和:检验数据在发送前后是否有改变。
- 序号和确认号:序号保证数据有序到达,确认序号保证对方收到了数据。
- 确认应答:对方在收到数据后会发送一个确认信息,表示自己收到了该数据。
- 超时重传:对丢失的数据或者是没有按时到达的数据重新发送。
- 连接管理:三次握手四次挥手
- 流量控制:根据对方的接收能力和网络状况,控制数据的发送。
- 拥塞控制:解决网络拥堵
效率:
- 滑动窗口:控制数据的发送
- 快速重传:也可以认为是保证可靠性的,在长链接中当连续收到三个相同的确认号时会对该数据重新发送。
- 延迟应答:提高网络吞吐量和传输效率
- 捎带应答:减少数据的发送次数
以上是关于计算机网络---传输层(tcpudp)的主要内容,如果未能解决你的问题,请参考以下文章