UNIX网络编程卷1:套接字联网API-第2章:传输层 TCP/UDP和SCTP
1.OSI模型OSI(open systems interconnection)计算机通信开放系统互连模型,是一个七层的理论模型(也就是说理论上分得很细致完善,但实际中设计实现中有出入) 实际过程中我们一般采用网际网协议族 物理层和数据链路层干的事情可以对应为网络硬件和设备驱动程序,如果不是要写驱动程序,一般我们不予关心。 网络层中规定的协议是什么呢? 就是我们经常说的IPV4和IPV6, 传输层中规定的协议是什么呢?TCP/UDP/SCTP,编写网络程序的人主要就是关注这一块 不通过传输层,直接使用IPV4和IPV6来写网络应用也是可以的,采用原始套接字(raw socket,套接字的一种)可以做到 理论中的会话层/表示层/应用层实际中合并成一层,统称应用层,一些网络应用,包括常见的web浏览器 qq 网易云音乐都是这一层的产物 我们需要牢牢记住上面的层次结构 2.传输层
讨论协议,我们可以从它所提供的服务入手
TCP(传输控制协议)
1.TCP提供客户和服务器之间的连接(connection):
TCP客户先与某个给定服务建立一个连接,再通过这个连接与那个服务器交换数据,然后终止这个连接。再说白话一点,就是tcp客户端和服务器端
建立一个只属于他们自己的通道,他们两个可以借着这个通道相互传东西,但是其他客户端和服务器段无法跨界到这里来。
2.TCP提供可靠性
当TCP向另一端发送数据时,它要求对端返回一个确认。若没有,则自动重传并等待更长时间。数次失败,则放弃并通知。也就是TCP有确认 重传 超时的机制来保证可靠性,此处的可靠性不是说数据100%能传递完全,而是说要么传到了,要么没传到对于我们来说是确认和明确的,没有任何模糊的可能。
3.TCP提供用于动态估算客户和服务器之间的往返时间(RTT)算法
用于知道等待一个确认需要多长时间,会持续估算一个给定连接的RTT
4.TCP通过给其中每个字节关联一个序列号对所发送的数据进行排序
5.TCP提供流量控制。
TCP总是告知对端在任何时刻它一次能够从对端接受多少字节的数据,这称为
对端窗口。借用一下http://blog.csdn.net/hackerwin7/article/details/21969307中的一段话:
TCP是一个滑动窗口协议,即一个TCP连接的发送端在某个时刻能发多少数据是由滑动窗口控制的,而滑动窗口的大小实际上是由两个窗口共同决定的,一个是接收端的通告窗口,这个窗口值在TCP协议头部信息中有,会随着数据的ACK包发送给发送端,这个值表示的是在接收端的TCP协议缓存中还有多少剩余空间,发送端必须保证发送的数据不超过这个剩余空间以免造成缓冲区溢出,这个窗口是接收端用来进行流量限制的,在传输过程中,通告窗口大小与接收端的进程取出数据的快慢有关。另一个窗口是发送端的拥塞窗口(Congestion window),由发送端维护这个值,在协议头部信息中没有,滑动窗口的大小的就是通告窗口和拥塞窗口较小值,所以拥塞窗口也看做是发送端用来进行流量控制的窗口。滑动窗口的左边沿向右移动称为窗口合拢,发生在发送的数据被确认时(此时,表明数据已被接收端收到,不会再被需要重传,可以从发送端的发送缓存中清除了),滑动窗口的右边沿向右移动称为窗口张开,发生在接收进程从接收端协议缓存中取出数据时。随着发送端不断收到的被发送数据的ACK包,根据ACK包中的确认序号和通告窗口大小使滑动窗口得以不断的合拢和张开,形成滑动窗口的向前滑动。如果接收进程一直不取数据,则会出现0窗口现象,即滑动窗口左边沿与右边沿重合,此时窗口大小为0,就无法再发送数据。 下面附一个TCP协议头的格式和滑动窗口的示意图(截自TCPIP协议详解):
图1.TCP头部结构 图2.滑动窗口示意图 6.TCP连接是全双工的 意味着在一个给定的连接上应用可以在任何时刻在进出两个方向上既可以发送数据又接收数据。相当于通道被一分为二变成两个子通道,通道数据流方向相反,对于每个子通道TCP都要跟踪诸如序列号和通告窗口大小等状态信息。通过某些手段,可以转换成一个单工连接。 7.TCP是一个字节流(byte-stream),消息无边界,要自行定义规则
TCP连接的建立和终止(重点来了)
牢牢记住上面的这张图 三路握手过程:(建立)(需要三个分节)
再看上述图时,要注意三路握手的具体过程分别发生在函数调用的什么时期,三路握手起始于客户connect的主动调用,当connect成功返回时,完成了前两路,并开始第三路,而服务器端在接收到ACK后,会阻塞到read(现在只需要有大致印象,以后详解)
TCP连接终止:(通常需要4个分节)
特别说明
TCP状态转换图 参见我另一篇博文 tcp状态转换详解 UDP(用户数据报协议)暂略,持续更新~~ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- scala – 为什么这个Spark示例代码不会加载到spark-shell中
- AngularJS学习之旅—AngularJS 简介(一)
- 错误:在遵循angularjs官方教程时无法找到chromedriver
- 什么时候应该使用Scala的“包”特殊标识符?
- typescript – Angular 2 Http – 如何使用finance_charts_
- scala – 对方法返回类型的类型推断
- angularjs – 占位符与angular/bootstrap不工作
- PHP缓存服务器之Redis
- bash – s3cmd sync是将错误的文件远程复制到错误的位置
- ruby-on-rails – Docker,使用docker flag -p 3000:3000