在写这篇文章之前,xxx已经写过了几篇关于改数据连接主题的文章,想要了解的朋友可以去翻一下之前的文章

一、TCP段格式:

TCP的段格式如下图所示

源端口号与目标端口号
源端口号和目标端口号,加上IP首部的源IP地址和目标IP地址唯一确定一个TCP连接。

序号
序号表示在这个报文段中的第一个数据字节序号。

确认号
仅当ACK标记为1时有效。确认号表示期望收到的下一个字节的序号。

头部长度
4位,TCP头部最多60个字节,最少20个字节

保存位
6位,必须为0

6个标记位
URG-紧急指针有效
ACK-确认序号有效
PSH-接收方应尽快将这个报文段交给应用层
RST-连接重置
SYN-同步序号用来发起一个连接
FIN-表示将要终止一个连接

窗口大小
通过窗口大小来达到流量控制。

校验和
对tcp表头与数据停止校验。

紧急指针
是一个正的偏移量,与序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据(也称为带外数据)的一种方式。

选项与填充(选项为4字节整数倍,否则用0填充)
最常见的可选字段是最长报文大小MSS(Maximum Segment Size),每一个连接方平日都在通信的第一个报文段中指明这个选项。它指明本端所能接收的最大长度的报文段(payload)。该选项如果不设置,默以为536(20+20+536=576字节的IP数据报),其中ip首部和tcp首部各20个字节,而internet 上标准的MTU (最小)为576B。

二、通信时序(3次握手-->传输数据-->4次挥手)

下图是一次TCP通信的时序图:

在这个例子中,首先客户端主动发起连接、发送请求,然后服务器端响应请求,然后客户端主动关闭连接。两条竖线表示通信的两头,从上到下表示时间的先后顺序,注意,数据从一端传到网络的另一端也需要时间,所以图中的箭头都是斜的。双方发送的段按时间顺序编号为1-10,各段中的重要信息在箭头上标出,例如段2的箭头上标着SYN, 8000(0), ACK 1001, <mss 1024>,表示该段中的SYN位置1,32位序号是8000,该段不携带有效载荷(数据字节数为0),ACK位置1,32位确认序号是1001,带有一个mss选项值为1024。

建立连接的过程:
1. 客户端收回段1,SYN位表示连接请求。序号是1000,这个序号在网络通信中用作临时的地址,每发一个数据字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发明丢包的情况,另外,规定SYN位和FIN位也要占一个序号,这次虽然没发数据,但是由于发了SYN位,因此下次再发送应该用序号1001。mss表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大帧长度,就必须在IP层分片,为了避免这种情况,客户端声明自己的最大段尺寸,提议服务器端发来的段不要超过这个长度。
2. 服务器收回段2,也带有SYN位,同时置ACK位表示确认,确认序号是1001,表示“我接收到序号1000及其之前所有的段,请你下次发送序号为1001的段”,也就是应答了客户端的连接请求,同时也给客户端收回一个连接请求,同时声明最大尺寸为1024。
3. 客户端收回段3,对服务器的连接请求停止应答,确认序号是8001。

在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请乞降应答在一个段中收回,因此一共有三个段用于建立连接,称为'''三方握手(three-way-handshake)'''。在建立连接的同时,双方协商了一些信息,例如双方发送序号的初始值、最大段尺寸等。

在TCP通信中,如果一方收到另一方发来的段,读出其中的目标端口号,发明本机并没有任何进程应用这个端口,就会应答一个包括RST位的段给另一方。例如,服务器并没有任何进程应用8080端口,我们却用telnet客户端去连接它,服务器收到客户端发来的SYN段就会应答一个RST段,客户端的telnet程序收到RST段后报告错误Connection timeout:

每日一道理
记不清有多少个夜晚,在我翻阅纸张的指间滑落;记不清有多少支蜡烛,在我的凝视中化为灰烬。逝者如斯,我时时刻刻会听见自己对生命承诺的余音,感到岁月的流转在渐渐稀释我的年少无知,我愿自己是一只上足了发条的时钟,在昼夜不停的流转中留下自己充实的每一刻。

数据传输的过程:
1. 客户端收回段4,包括从序号1001开始的20个字节数据。
2. 服务器收回段5,确认序号为1021,对序号为1001-1020的数据表示确认收到,同时请求发送序号1021开始的数据,服务器在应答的同时也向客户端发送从序号8001开始的10个字节数据,这称为piggyback。
3. 客户端收回段6,对服务器发来的序号为8001-8010的数据表示确认收到,请求发送序号8011开始的数据。

在数据传输过程中,ACK和确认序号是非常重要的,应用程序交给TCP协议发送的数据会暂存在TCP层的发送缓冲区中,收回数据包给对方以后,只有收到对方应答的ACK段才晓得该数据包确切发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丧失了数据包或者丧失了对方发还的ACK段,经过等待超时后TCP协议主动将发送缓冲区中的数据包重发。

这个例子只描述了最简略的一问一答的情景,现实的TCP数据传输过程可以收发很多数据段,虽然典型的情景是客户端主动请求服务器被动应答,但也不是必须如此,事实上TCP协议为应用层供给了全双工(full-duplex)的服务,双方都可以主动甚至同时给对方发送数据。

如果通信过程只能采用一问一答的方式,收和发两个方向不能同时传输,在同一时间只允许一个方向的数据传输,则称为'''半双工(half-duplex)''',假设某种面向连接的协议是半双工的,则只需要一套序号就够了,不需要通信双方各自维护一套序号。

关闭连接的过程:
1. 客户端收回段7,FIN位表示关闭连接的请求。
2. 服务器收回段8,应答客户端的关闭连接请求。
3. 服务器收回段9,其中也包括FIN位,向客户端发送关闭连接请求。
4. 客户端收回段10,应答服务器的关闭连接请求。

建立连接的过程是三方握手,而关闭连接平日需要4个段,服务器的应答和关闭连接请求平日分歧并在一个段中,因为有连接半关闭的情况(调用shutdown而不是close),这种情况下客户端关闭连接以后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止。

三、滑动窗口和流量控制

如果发送端发送的速度较快,接收端接收到数据后处理的速度较慢,而接收缓冲区的大小是牢固的,就会丧失数据。TCP协议通过'''滑动窗口(SlidingWindow)'''机制解决这一问题。看下图的通信过程。

1. 发送端发起连接,声明最大段尺寸是1460,初始序号是0,窗口大小是4K,表示“我的接收缓冲区还有4K字节闲暇,你发的数据不要超过4K”。接收端应答连接请求,声明最大段尺寸是1024,初始序号是8000,窗口大小是6K。发送端应答,三方握手结束。
2. 发送端收回段4-9,每一个段带1K的数据,发送端根据窗口大小晓得接收端的缓冲区满了,因此停止发送数据。
3. 接收端的应用程序提走2K数据,接收缓冲区又有了2K闲暇,接收端收回段10,在应答已收到6K数据的同时声明窗口大小为2K。

4. 接收端的应用程序又提走2K数据,接收缓冲区有4K闲暇,接收端收回段11,重新声明窗口大小为4K。
5. 发送端收回段12-13,每一个段带2K数据,段13同时还包括FIN位。
6. 接收端应答接收到的2K数据(6145-8192),再加上FIN位占一个序号8193,因此应答序号是8194,接收端同时声明窗口大小为2K。
7. 接收端的应用程序提走2K数据,接收端重新声明窗口大小为4K。
8. 接收端的应用程序提走剩下的2K数据,接收缓冲区全空,接收端重新声明窗口大小为6K。
9. 接收端的应用程序在提走全部数据后,决议关闭连接,收回段17包括FIN位,发送端应答,连接完全关闭。

上图在接收端用小方块表示1K数据,实心的小方块表示已接收到的数据,虚线框表示接收缓冲区,因此套在虚线框中的空心小方块表示窗口大小,从图中可以看出,随着应用程序提走数据,虚线框是向右滑动的,因此称为滑动窗口。

从这个例子还可以看出,发送端是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),在底层通信中这些数据可能被拆成很多数据包来发送,但是一个数据包有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是轻易出现粘包问题的原因。而UDP是面向消息的协议,每一个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。

四、TCP如何保障可靠性

1、应用数据被分割成TCP以为最适合发送的数据块,称为段传递给IP层。
2、当TCP收回一个段后,它启动一个定时器,等待目标端确认收到这个报文段。如果不能实时收到一个确认,将重发这个报文段。
3、当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,平日将推迟几分之一秒。
4、TCP将坚持它首部和数据的校验和。这是一个端到端的校验和,目标是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将抛弃这个报文段并且不确认(致使对方超时重传)
5、TCP承载于IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对收到的数据停止重新排序。
6、IP数据报会产生重复,TCP的接收端必须抛弃重复的数据。
7、TCP还能供给流量控制。TCP连接的每一方都有必定大小的缓冲空间。

参考:

《Linux C 编程一站式学习》

《TCP/IP详解 卷一》

文章结束给大家分享下程序员的一些笑话语录: 关于编程语言
如果 C++是一把锤子的话,那么编程就会变成大手指头。
如果你找了一百万只猴子来敲打一百万个键盘,那么会有一只猴子会敲出一 段 Java 程序,而其余的只会敲出 Perl 程序。
一阵急促的敲门声,“谁啊!”,过了 5 分钟,门外传来“Java”。
如果说 Java 很不错是因为它可以运行在所有的操作系统上,那么就可以说 肛交很不错,因为其可以使用于所有的性别上。

--------------------------------- 原创文章 By
数据和连接
---------------------------------

数据连接linux网络编程之TCP/IP基础(四):TCP连接的建立和断开、滑动窗口相关推荐

  1. linux网络编程之posix 线程(四):posix 条件变量与互斥锁 示例生产者--消费者问题

    http://blog.csdn.net/jnu_simba/article/details/9129939 一.posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行, ...

  2. Linux网络编程之TCP状态转移

    Linux网络编程之TCP状态转移 一.TCP状态转移时序 二.半关闭及shutdown函数 一.TCP状态转移时序 TCP状态转移图: netstat -apn | grep client 查看客户 ...

  3. Linux网络编程之IP地址转换为无符号整数的方法

    Linux网络编程之IP地址转换为无符号整数的方法,代码如下:(没考虑异常输入) #include <stdio.h> #include <string.h> #include ...

  4. Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解

    Linux网络编程之sockaddr与sockaddr_in,sockaddr_un结构体详细讲解 (1)sockaddr struct sockaddr { unsigned  short  sa_ ...

  5. linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时

    一.使用alarm 函数设置超时 C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13   void handler( int sig) { } signal(SIGALRM ...

  6. linux网络编程之Socket编程

    (1)socket套接字 1)在linux环境下,socket用于表示进程间网络通信的特殊文件类型,其本质是内核借助缓冲区形成的伪文件(不占磁盘空间,除此之外还有二进制文件,管道,字符文件). 2)伪 ...

  7. linux网络编程之socket编程(六)

    经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:"真爱生活,珍惜生命",好了,言归正传. ...

  8. 嵌入式linux ntpd命令,嵌入式Linux网络编程之:实验内容——NTP协议实现

    本文引用地址:http://www.eepw.com.cn/article/257114.htm 10.4实验内容--NTP协议实现 1.实验目的 通过实现NTP协议的练习,进一步掌握Linux网络编 ...

  9. linux ioctl网络参数设置,Linux 网络编程之ioctl函数

    1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...

最新文章

  1. Makefile的东西
  2. 【OkHttp】OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 )
  3. 小程序f2自定义html,微信小程序个人产品添加上传样式设计制作开发教程(2)
  4. 杭州 | PMCAFF 产品经理第一课,面向3-5年产品经理,全面提升产品战略能力
  5. 冠榕智能灯光控制协议分析(controller init)
  6. python 工具ScreenShoot
  7. 在iOS项目中,这样才能完美的修改项目名称
  8. POJ 3518 Prime Gap(素数)
  9. 基于snowflake的序列号生成器
  10. 【数据结构】——各种树的定义
  11. 大数据产品价值主张_从「商业模式画布」看产品的价值主张和用户需求
  12. 考研经验-从入门到成功-有干货-全/非全考研-在职考研
  13. Python学习笔记--Flask小项目之仿豆瓣电影界面
  14. 内存卡打不开需要格式化怎么恢复数据
  15. 软件自动升级解决方案(一)
  16. C++: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
  17. PLSQL执行SQL脚本文件「适用批量」- 工具使用篇
  18. 网络安全实验1 Sniffer Pro网络分析器应用实验
  19. [附源码]java毕业设计电影影评网
  20. 鼎普计算机保密检查系统,敏感电子信息集中管控平台系统

热门文章

  1. linux命令:ln 使用方法
  2. ASP.NET重用代码技术 - 代码绑定技术
  3. Python3中collections.OrderedDict介绍
  4. vc6静态库的生成和调用
  5. 【Qt】一个使用QEventLoop时,遇到的教训
  6. 扬州市大学计算机专业录取分数线,“计算机网络技术”专业录取分数线
  7. python turtle画画 30排以内_Python竟能画这么漂亮的花,帅呆了(代码分享)
  8. 【工具软件】Xmind的使用
  9. Linux的常用命令!
  10. “接口”的定义及其与“抽象类”的区别