TCP/IP协议(5):传输层之TCP
一、TCP报文

上图为TCP报文的格式,可以看到TCP头部占20个字节,其中红色圆圈中每一项占一位,表示TCP报文的类型,置1表示该项有效。
SYN表示建立连接。
FIN表示关闭连接。
ACK表示响应、确认。
PSH表示带有PUSH标志的数据传输。
RST表示连接重置或拒绝连接请求。
URG表示紧急指针有效。
其中,ACK是可能与SYN或FIN或PSH同时置1的。
二、TCP(传输控制协议)是面向连接的,可靠的,字节流服务。
IP协议是Internet Protocol互联网协议,它能够使互联网上两台计算机进行通信,包装了计算机之间可以发送和接收数据,但IP协议不能解决数据包在传输过程中可能出现的协议。TCP协议是Transmission Control Protocol传输控制协议,它需要两台计算机通信之前先进行“连接”。TCP会收集和处理IP通信的数据包,如果数据包太大的话会将其分割为报文段,并将其按适当的次序放好传送,接收方收到报文段后根据其序号以正确的顺序重组接收。TCP还使用重传机制,发送方发送一个消息后需要对方的一个确认信息,如果在一定时间内没有收到的话就再次重发刚才的消息。这样TCP协议就保证了数据包在通信传输中的可靠性。
1、面向连接
面向连接即双方通信前要先建立连接,通信结束双方要关闭连接,而UDP却不用。
建立TCP连接需要三次握手:客户端调用connect()向服务器建立连接(发送SYN包),服务器收到后确认客户端的连接请求并向客户端建立连接(发送ACK+SYN包),客户端收到后确认服务器的连接请求(发送ACK包)。
关闭TCP连接需要四次挥手:本端调用closesocket()关闭套接字(发送FIN包),对端收到后确认这个关闭(发送ACK包),对端调用closesocket()关闭套接字(发送FIN包),本端收到后确认这个关闭(发送ACK包)。
2、可靠性和滑动窗口
TCP的可靠性主要体现在:
①、报文发送方会等待接收方对于数据报的ACK回复确认,超时的话会重新发送。
②、报文接收方会对数据报文进行校验,出错则不对报文进行确认,使发送方重新发送。
③、IP协议并不能保证数据到达的次序,而UDP也没有对数据帧进行乱序处理,所以UDP同样不保证数据顺序。而TCP协议则对乱序进行处理以保证数据按照顺序到达:每个报文都有一个序号和确认号,序号是当前数据包的第一个数据字节在发送数据流中的偏移量,确认号则为希望接收的下一个数据字节的序号。如果当前接收的数据序号和期望接收的序号不同的话即出现乱序,TCP会将乱序的报文先在缓存中保存起来,以备后用。如果这个乱序的报文实在是“乱”的很厉害则不会处理该报文,也不会发送对应的ACK。
TCP的可靠性通过“滑动窗口”机制来实现,从TCP首部可以看到滑动窗口的大小用16位来保存,故其最大为2^16-1即65535个字节,另外在TCP的选项字段中还包含了一个TCP窗口扩大因子,窗口扩大因子用来扩大TCP窗口,可把原来16bit的窗口,扩大为31bit。
滑动窗口可以分为发送窗口和接收窗口,因为TCP是双工的协议,所以TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”。“接收窗口”的大小取决于应用、系统、硬件的限制,“发送窗口”是根据连接时对端告知的其“接收窗口”大小来构造的。而且本端"发送窗口"的大小会随着对端"接收窗口"的大小而改变。
对于TCP会话的发送方,任何时候在其发送缓存内的数据都可以分为4类,“已经发送并得到对端ACK的”,“已经发送但还未收到对端ACK的”,“未发送且对端允许发送的”,“未发送但对端不允许发送”。其中“已经发送但还未收到对端ACK的”和“未发送但对端允许发送的”这两部分数据称之为发送窗口。对于TCP的接收方,在某一时刻在它的接收缓存内存在3种。“已接收”,“未接收准备接收”,“未接收但还未准备接收”(由于ACK直接由TCP协议栈回复,默认无应用延迟,不存在“已接收未回复ACK”)。其中“未接收准备接收”称之为接收窗口。
(以下参考和转载自:TCP 滑动窗口(发送窗口和接收窗口),https://my.oschina.net/xinxingegeya/blog/485650)
如下图,中间的两部分称为发送窗口:

而当收到接收方新的ACK对于发送窗口中后续字节的确认时,窗口滑动,如下图,当收到ACK=36时窗口滑动:

滑动窗口的传输可靠性是建立在“确认重传”基础上的:发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界,接收窗口只有在前面所有的段都确认了的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认,以此确保对端会对这些数据重传。
3、流量控制
TCP协议会根据情况自动改变滑窗大小,以实现流量控制,它主要是通过控制本端TCP接收窗口大小来对对端的发送窗口流量限制:
应用程序在需要时,比如对端发送数据太快的时候,TCP协议栈会缩小TCP的接收窗口,然后TCP协议栈在下个段发送时包含新的窗口大小通知给对端,对端按通知的窗口来改变发送窗口,以此达到减缓发送速率的目的。主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
(以下参考和转载自 一站式学习Wireshark,http://blog.jobbole.com/71925/)
如下图,客户端向服务器发送数据,服务器接收窗口大小是5000字节。客户端发送了2500字节后服务器缓冲区中可用大小还剩2500字节,紧接着客户端又发送了2000字节,从而缓冲区只剩500字节的可用大小。这时服务器向客户端发送确认信息,对缓存中数据进行处理并清空缓存。以上过程重复进行,客户端又发送3000字节和1000字节,服务器缓存减少至1000字节,客户端再次确认数据并处理缓存中内容。

如果客户端发送数据太快或服务器端接收数据太慢的话则可能会造成丢包和数据损坏,所以种情况的话TCP会减小接收窗口的大小,从而控制发送方发送行为。当接收窗口减小后,通过返回给发送端的ACK报文的TCP头窗口大小值来告知发送端减小其发送窗口。如下图:服务器初始窗口大小为5000字节。客户端发送2000字节,之后又发送了2000字节,缓冲区中只有1000字节可用。服务器意识到缓冲区正在快速填满,它知道如果数据继续以此速率传输,很快会有报文丢失。为了防止报文丢失,服务器发送确认信息给客户端,更新窗口大小为1000字节。结果,客户端减少数据发送,服务器以可以接受的速率处理缓存内容,即保持数据流以稳定的速率传输。当服务器能够更加快速的处理报文时,它会发送一个较大窗口的ACK报文。

某些特殊情况下,服务器可能由于内存不足,处理能力不够,或其他原因导致无法再处理从客户端发送的数据。当这种情况发生时,服务器会发送窗口为0的报文。当客户端接收到此报文时,它会暂停所有数据传输,但会保持与服务器的连接以传输探测(keep-alive)报文。探测报文在客户端以稳定间隙发送,以查看服务器接收窗口状态。一旦服务器能够再次处理数据,将会返回非零值窗口大小,传输会恢复。
4、拥塞控制
TCP的“拥塞控制”是为了防止过多的数据注入网络中形成网络堵塞。它通过使用几种算法来实现,如慢开始、拥塞避免、快重传和快恢复,TCP会在合适的情况选择合适的算法来对数据传输进行控制以实现“拥塞控制”。
5、Nagle算法
Nagle算法通过减少小的封包的传送量来提高TCP/IP的效能,比如某个应用连续发送1字节的数据,而TCP包头就占用40字节,所以导致了很大的浪费,而且这些小的封包如果在短时间内大量发送的话会造成拥塞,拥塞会造成重传,重传可能会引发更严重的拥塞,导致网络吞吐量下降。Nagle算法伪代码如下:
if (有新数据要发送)
{
if (可发送的数据>=MSS and 窗口大小>=MSS)
{
立即发送完整MSS大小的segment
}
else
{
if (尚有未被对方ACK的数据)
在下一個确认(ACK)封包收到前,将数据排入缓冲区队列
else
立即发送数据
}
}
在TCP编程中我们可以通过setsockopt()的TCP_NODELAY选项来禁止Nagle算法,然而只有某些特殊的应用才必须禁用Nagle算法。大部分应用程序禁用Nagle是因为他们用一系列小规模的写操作来发送逻辑上相关联的数据造成的发送性能问题,如果有一种操作能够将这些数据合并起来一起发送出去那就不必禁用Nagle算法——那就是使用writev()函数(windows下WSASend()函数),它可以完成一次发送多个缓冲区中的数据来进行集中发送。
转载参考出处:TCP 滑动窗口,https://my.oschina.net/xinxingegeya/blog/485650
一站式学习Wireshark,http://blog.jobbole.com/71925/
http://www.cnblogs.com/woaiyy/p/3554182.html
TCP/IP协议(5):传输层之TCP的更多相关文章
- TCP/IP 协议图--传输层中的 TCP 和 UDP
TCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP. TCP 是面向连接的.可靠的流协议.流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然可以保证发送的顺序,但 ...
- 从网卡发送数据再谈TCP/IP协议—网络传输速度计算-网卡构造
在<在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP>里面提到 单个TCP包每次打包1448字节的数据进行发送(以太网Ethernet最大的数据帧是1518字节,以 ...
- TCP/IP中的传输层协议TCP、UDP
TCP提供可靠的通信传输,而UDP则常用于让广播和细节控制交给应用的通信传输. 传输层协议根据IP数据报判断最终的接收端应用程序. TCP/IP的众多应用协议大多以客户端/服务端的形式运行.客户端是请 ...
- TCP/IP五层模型-传输层-TCP协议
1.定义:TCP是一种面向连接.可靠的.基于字节流的传输控制协议. 2.应用场景:TCP为可靠传输,适合对数据完整性要求高,对延时不敏感的场景,比如邮件. 3.TCP报文:①TCP报文格式: ②TC ...
- TCP/IP入门(3) --传输层
原文:http://blog.csdn.net/zjf280441589/article/category/1854365 传输层的主要功能 1)传输层为应用进程之间提供端到端的逻辑通信(网络层是为主 ...
- TCP/IP 协议:链路层概述
我们以一个常见的查看IP指令为出发点(ifconfig -a): 1.链路层是什么 链路层是指硬件层协议.也即网络所使用的硬件,比如:以太网(后文主要讨论对象),令牌环网,FDDI已经RS-232 ...
- TCP/IP协议族各层的作用
从协议分层模型方面来讲,TCP/IP由四个层次组成:数据链路层.网络层.传输层.应用层一.数据链路层 数据链路层是负责接收IP数据报并通过网络发送之,或者从网络上接收物理帧,抽出IP数据报,交给IP层 ...
- TCP/IP协议中的UDP与TCP的区别
TCP面向连接,UDP面向非连接即发送数据前不需要建立链接TCP提供可靠的服务(数据传输),UDP无法保证,它没有TCP的接受确认.窗口等机制,因此也不需要交换控制信息:发生丢包也一概不负责.TCP面 ...
- TCP/IP五层模型-传输层-UDP协议
1.定义:UDP:是非面向连接.不可靠的用户数据包协议. 2.应用场景:适合对数据完整性要求不高,但对延迟很敏感,比如即时通信(语音视频聊天等). 3.UDP报文格式: 4.用UDP传输数据的应用层 ...
- TCP/IP 协议 OSI七层协议
------------------你来自何处并不重要,重要的是你要去往何方,人生最重要的不是所站的位置,而是所去的方向.人只要不失去方向,就永远不会失去自己! day 27 # # -------- ...
随机推荐
- gitbook的学习
gitbook安装与使用之windows下搭建gitbook平台 最近需要在GitBook中去阅读电子书 安装nodejs cnpm安装gitbook 解压书籍文件,并cd到书籍文件目录 gitboo ...
- JSP跳转到指定位置
通常情况下用如下写法即可 onclick='window.location.hash = "某元素的id";' 但我的元素是动态生成的,直接生成代码附带多个单引号和双引号,js语言 ...
- Swift 常量、变量、条件判断
- 常量用 let ,变量用 var - // Optional为可选项,// 可用类型值 + ? 代替 let x: Optional = 10 let y: Int? = 5 print(x! + ...
- @__CheckForDebuggerJustMyCode@4
最近在编译一个项目MiniFSWatcher,其中有一部分程序需要安装驱动minispy,编译过程中报错 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK2019 无法解析的外部符号 @ ...
- 金老师的经典著作《一个普通IT人的十年回顾》
学习人生 -------一个普通IT人的十年回顾(上)序从1994到2003,不知不觉之间,我已在计算机技术的世界里沉浸了十年.有位哲人说过:如果一个人能用十年的时间专心致志地 ...
- c# txt内存映射技术总结
对于大文件操作,readline 的方式读取文档,那操作起来跟蜗牛爬一样的慢了, 于是使用内存映射技术, 参考微软的这个使用方法说明 https://msdn.microsoft.com/zh-cn/ ...
- c# 关于字典dictionary 按时间排序
上文中说到sortedlist 排序是键排序,不符合项目要求问题,接着使用字典dictionary 对value 为时间按照升序排序,问题解决.中间涉及到linq的使用.还有其他的写法,但发现下边的写 ...
- 【转】我为什么把think in java 读了10遍
我在想写这篇博文之前,就曾经对我媳妇(她是做web前端的)讲,我把think in java看了几次几次,媳妇那时就用很羡慕和莫名的眼神看着我说,你真有毅力,我当时就蒙了,我以为她会说,你现在基础一定 ...
- 5O - 产生冠军
有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则如下: 如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C. 如果A打败了B,B又打败了 ...
- Pandas设置值
1.创建数据 >>> dates = pd.date_range(', periods=6) >>> df = pd.DataFrame(np.arange(24) ...