宁波p2p网站建设,锦州网站做优化,淘宝开店流程步骤图片,邢台168交友更多关于UDP协议和TCP协议请移步官网#xff1a;https://www.rfc-editor.org/standards#ISUDP标准协议文档-RFC 768TCP标准协议文档-RFC 793UDP协议详解UDP协议的特点#xff1a;无连接、不可靠传输、面向数据报和全双工。UDP协议报文结构#xff1a;关于端口号#xff1a;…更多关于UDP协议和TCP协议请移步官网https://www.rfc-editor.org/standards#ISUDP标准协议文档-RFC 768TCP标准协议文档-RFC 793UDP协议详解UDP协议的特点无连接、不可靠传输、面向数据报和全双工。UDP协议报文结构关于端口号端口都是使用2个字节16个bit位来表示一个端口号的取值范围在0-65535之间。但是并不是所有的端口都可以被咱们程序猿所使用。我们自己写的程序绑定的端口一般是从1024开始的。0-1023这个范围的端口被称为“知名端口号”即这些端口号是属于已经分配了一些知名的广泛使用的应用程序。1023以下的端口号一般是不建议使用。关于UDP报文长度对于UDP来说报头一共就是8个字节分成四个部分每个部分两个字节。UDP报文长度也是用2个字节来表示的2个字节的范围就是0-65535换算成单位就是64kb也就是说一个UDP数据报最大也就能够传输64kb的数据。这个数值对于目前的传输要求来说显然是很小的如果应用层数据报超过了64KB对于UDP来说就需要在应用层通过代码的方式针对应用层数据报进行手动的分包拆成多个包通过多个UDP数据报进行传输本来需要send一次现在需要send多次或者换成TCP协议因为TCP协议没有长度的限制。关于校验和校验和的作用就是验证传输的数据是否是正确的。网络传输的本质就是光电信号在传输过程中可能会受到一些干扰就可能出现“比特翻转”的情况即1-0 或 0 - 1就会造成数据改变。这样的现象是客观存在的因此就引入了校验和来进行鉴别。针对数据内容进行一系列的数学运算得到一个比较短的结果2个字节当接收方收到这个数据之后也会进行相同逻辑的数学运算也会得到一个结果。如果两次校验和的结果是一样的则证明传输的数据是正确的反之证明数据在传输过程中发生了改变。当然在低端情况下就算数据内容不一致那么也会得到一个相同的校验和那么这种是极小概率的可以忽略不计。TCP协议详解10个核心机制TCP协议的特点有连接、可靠传输、面向字节流和全双工。确认应答实现可靠传输的最核心机制。A给B发一个消息B收到之后就会返回一个应答报文ACK此时A收到之后就知道刚才发送的信息已经顺利到达B了。但是如果A给B发送了多条消息网络传输中存在“先发后至”现象那么B收到的信息的顺序也是错乱的那么B返回A的应答报文到达的顺序也是可能发生变动的这就有可能会因为顺序错乱而带来语义上的歧义。为了解决上述问题给传输的数据和应答报文都进行编号。这样即使顺序错乱了也可以根据序号来区分当前应答报文是针对哪个数据进行的了。任何一条数据包括应答报文都是有序号的确认序号是只有应答报文有一条报文是否是应答报文取决于ACK这个标志位是否是1。TCP可靠传输能力最主要就是通过确认应答机制来保证的。通过应答报文就可以让发送方清楚的知道传输是否成功进一步的引入了序号和确认序号针对多组数据进行详细的区分。超时重传当发送的数据丢了或者返回的ack丢了这种情况叫做丢包。但是对于发送方来说就是没有收到ack区分不了到底是哪一种情况造成的。因此TCP就引入了重传机制在丢包的时候重新再发一次同样的数据。TCP引入了一个时间阈值发送方发了一个数据之后就会等待ack此时开始计时如果超过了这个时间阈值还没有收到ack就视为丢包就重新传输。但是会引入一个问题由于重传就会导致接受方同样的数据就会被收到多次这是比较恐怖的比如支付问题。但是TCP对于这种情况是有处理的TCP可以对重复数据去重。TCP存在一个“接受缓冲区”这样的存储空间接收方操作系统内核里的一段内存每个TCP的socket对象都有一个接受缓冲区其实也有一个发送缓冲区。根据数据的序号很容易识别当前接受缓冲区里面的重复数据如果重复了就丢弃后来的这份数据保证了应用程序read读取到的数据一定是不重复的。由于去重和重新排序机制的存在发送方只要发现ACK没有按时到达就会重传数据。即使重复了即使顺序乱了都没事接收方都能很好的处理好(去重和排序都依赖TCP报头的序号)。重传达到一定次数的时候就不会再继续重传会认为网路出现故障。接下来TCP会尝试重置连接(相当于断开重连一样)如果重置还是失败彻底断开连接了。小结:可靠传输是TCP最核心的部分。TCP的可靠传输就是通过确认应答超时重传来进行体现的。其中确认应答描述的是传输顺利的情况。超时重传描述的是传输出现问题的情况。这两者相互配合,共同支撑整体的TCP可靠性。连接管理建立连接三次握手建立连接就是通信双方各自要记录对方的信息彼此之间要相互认同。客户端主动给服务器发起的建立连接请求,称为SYN同步报文段。所谓的三次握手本质上是四次交互通信双方各自要向对方发起一个“建立连接”的请求同时,再各自向对方回应一个ack。但是,中间两次交互,是可以合并成一次交互的因此就构成了“三次握手过程。中间两次的交互是必须合并的因为封装分用两次一定比封装分用一次的成本更高。三次握手的重要作用就是建立彼此之间的认同验证通信双方各自的发送能力和接收能力是否正常在一定程序上保证了TCP传输的可靠性。如果是只有两次握手则验证不了双方通信都是正常的。举个例子如果只有两次握手那么站在男生的角度知道了女神同意我请她吃饭。但是站在女神的角度她不知道男生是否同意她请她吃饭。在建立连接阶段主要有两个状态LISTEN(listen):为服务器的状态表示服务器已经准备就绪随时可以有客户端来连接。ESTABLISHED(established):客户端和服务器都有这个状态表示连接建立完成接下来就可以正常通信了。断开连接四次挥手四次挥手和三次握手非常类似都是通信双方各自向对方发起一个断开连接的请求再各自给对方一个回应。四次挥手中间的两次交互是不能合并的之所以三次握手中间两次能够合并是因为三次握手的中间两次能够合并是因为他俩是同一时机SYN 和 ACK具体来说,三次握手这三次交互过程,是纯内核中完成的(应用程序感知不到也干预不了)服务器的系统内核收到syn之后,就会立即发送ack 也会立即发送syn。对于四次挥手来说FIN的发起不是由内核控制的而是由应用程序调用socket的close方法(或者进程退出)才会触发FIN。ACK则是由内核控制的是收到FIN之后立即返回ACK而服务器的应用程序执行到对应的close方法,才会触发的FIN这两者之间就会隔了一个时间差具体时间差是多少取决于代码的写法。所以基于上述原因FIN 和 ACK 并不完全是同一时机的所以四次挥手中的中间两次是不能合并的。四次挥手涉及到两个重要的状态CLOSE_WAIT: 出现在被动发起断开连接的一方建立连接一定是客户端主动发起请求断开连接可能是客户端主动发起也可能是服务器主动发起等待关闭等待调用close方法关闭socket。TIME_WAIT: 出现在主动发起断开连接的一方假设是客户端主动发起断开连接那么当客户端进入TIME_WAIT状态的时候相当于四次挥手在客户端这边已经结束了但是此时这里的TIME_WAIT要保持当前的TCP连接状态不要立即释放。TIME_WAIT保留一段时间的连接是因为此时最后一个ack刚刚发出去还没有到呢防止ack丢包。在三次握手和四次挥手过程中都是存在超时重传的。如果是最后一个ACK 丢包了,站在服务器的视角来看服务器是不知道是因为ACK丢了还是自己发的FIN 丢了所有统一视为FIN丢了统一进行重传操作。既然服务器可能要重传FIN客户端就需要能够针对这个重传的FIN进行ACK响应很明显,如果刚才彻底把连接释放了,这样的ACK就无法进行了。因此使用TIME_WAIT状态保留一定的时间,就是为了能够处理最后一个ACK 丢包的情况,能够在收到重传的FIN之后,进行ACK响应。那TIME_WAIT具体保持多长时间,就真正释放呢?按照一般的经验来说定义MSL为A传输数据到B所花费的时间经验值那么就约定TIME_WAIT保持2 MSL。滑动窗口可靠性和传输效率本身来说是矛盾的在保证可靠性的基础上来尽可能的提高传输效率就引入了滑动窗口。对于基本确认应答的情况来说,每次发一个数据,都需要等等 ack到了再发下一个。滑动窗口的本质就是不等待的批量发送一组数据然后使用一份时间来等待着一组数据的多个ACK 。把不需要等待,就能直接发送的数据的最大的量,称为窗口大小。如果出现丢包的情况就分为两种情况了第一种就是ack丢了这种情况是不需要做任何处理的关键在于有确认序号的存在表示从该序号往前的所有数据都已经确认到达了。第二种就是数据丢了由于1001-2000丢包了接下来2001-3000到达主机B之后,B给A返回的ACK确认序号仍然是1001(此时和你发来的这个数据序号是啥,关系不大了)会一直索要1001开头的数据直到1001开头的数据传输过来“快速重传-超时重传在滑动窗口下的变形”如果下面还有数据丢包的情况那么还会继续索要下一个直到没有数据丢包。流量控制流量控制是一种干预发送的窗口大小的机制。滑动窗口,窗口越大,传输效率就越高(一份时间,等的ack 就越多)。但是滑动窗口无限大也有以下问题1.完全不等待ack,可靠性可能得不得保障2.窗口太大,也会消耗大量的系统资源3.发送速度太快,接收方处理不过来接收方的处理能力,就是一个很重要的约束依据发送方发的速度,不能超出接收方的处理能力。流量控制要做的工作就是根据接收方的处理能力,协调发送方的发送速率。流量控制的实现方式就是根据接收方接受缓冲区的剩余大小然后把这个值通过ack报文返回给发送方然后发送方就根据这个值来决定接下来发送的速率是多少窗口的大小是多少。由于接收方缓冲区剩余空间是一直在动态变化的所以每次返回ack 带的窗口大小都在变化发送方也是在动态调整。当窗口大小为0,发送方A就要暂停发送暂停发送的等待过程中,会给主机B定期发送窗口探测报文。这个报文不携带具体的业务数据,只是为了触发ack查询窗口大小。拥塞控制流量控制和拥塞控制共同决定发送方的窗口大小是多少。流量控制考虑的是接收方的处理能力而拥塞控制描述的是传输过程中中间节点的处理能力。根据木桶效应应该要找出处理能力最差的节点因为发送方和接收方的处理能力可以被衡量但是中间节点的处理能力不容易被衡量。把中间所有的节点看作是一个大的节点通过实验的方式逐渐找到了一个合适的窗口的大小。拥塞窗口和流量控制的窗口,共同决定了发送方实际的发送窗口(拥塞窗口和流量控制窗口的较小值)延时应答延时应答也是提升效率的机制也是在滑动窗口的基础之上再完善的一些机制。延时应答就是在收到数据之后不是立即返回ACK了而是稍微等会再返回。等待的时间里,接收方的应用程序,就能够把接收缓冲区的数据给消费一些。实际上延时应答采取的方式,就是在滑动窗口下,ack 不再每一条数据都返回了而是比如隔1条或者多条返回一个ack。实际上剩余空间的大小变化是一个复杂的过程,既取决于发送方的发送也取决于接收方的处理。捎带应答也是提高效率的方式在延时应答的基础之上引入的捎带应答。服务器客户端程序,最典型的模型,就是一问一答。由于延时应答机制就导致等待ACK的过程中B就要给A发送业务数据了就可以让业务数据捎上这个ACK一起发过去就行了。本来返回ACK和发送业务数据是不同的时机但是在延时应答下可能成为相同时机,就合并了。TCP三次握手,本身就是相同时机所有三次握手是一定会合并的。但是此处引入了延时应答就和四次挥手的合并比较像了有一定概率会被合并。粘包问题因为TCP是面向字节流的所有在接收缓冲区,其实是把收到多个数据都放到一起了那么应用程序read读取的时候,读到哪里才算是一个完整的应用层数据报呢?这就导致一次读到的数据,可能是半个应用层数据报,可能是一个应用层数据报,也有可能是多个应用层数据报。所以解决方案其实很简单在应用层约定好应用层协议尤其是明确应用层数据报和应用层数据报之间的边界。有两种方式一是约定好分割符二是约定每个包的长度。异常情况传输过程中出现了不可抗力的因素比如进程奔溃、主机关机正常流程关机、主机掉电、网线断开等等。对于进程奔溃和主机关机正常流程关机就是进程没了对应的PCB就没了对应的文件描述符表就释放了。相当于socket.close()此时内核会继续完成四次挥手。此时其实仍然是一个正常断开的流程主机关机要先杀进程然后才正式关机(杀死进程的过程中,也就是和上面一样触发四次挥手)。对于主机掉电和网线断开显然是来不及四次挥手了。假设是接收方掉电了发送方仍然在继续发数据,发完数据要等待ack.ack 如果等不到就会超时重传但是再怎么重传,也收不到ack 重传几次,还没有应答尝试重置 tcp连接(复位报文段RST)。显然这个重置也会失败然后单方面放弃连接了。如果是发送方掉电接收方发现没数据了。没数据是发送方挂了?还是发送方要组织下语言,稍等会再发?接收方完全不知道只能先等。接收方需要周期性的给发送方发送一个消息,确认下对方是否还工作正常也就是发送心跳包。