由 TCP 报文格式谈 TCP — 源端口号、目的端口号、报文段序号(一)

来源:互联网 发布:linux网络文件系统鼻祖 编辑:程序博客网 时间:2024/04/28 01:19

博主曾经学 Linux 的时候,觉得知识点很多很难很困惑,遂问一前辈,怎么才能学通学精达到融会贯通,前辈意味深长地丢给博主三个字:写博客。博主于是屁颠屁颠儿地跑过来写博客了,本人大三网络工程专业,最近为了找实习在学习 linux,刚好看到 TCP 部分,那就拿 TCP 报文分析来做第一篇博文吧~

首先要有一个概念,即 TCP 首部最小为20个字节,20个字节分为5行,每行为4个字节,也就是32位;谈到这里大家应该会在脑海中画一个长325的矩形,如果可以的话再给它分行,分为5行。就像下面这个样子:

这 20  个字节是怎么来的呢?又以什么样的形式存在呢?里面包含什么内容呢?



那么让我们来想想这个报文中应该有什么东西,首先 TCP 是用来建立连接的,是在什么情况下用来建立连接呢?我们知道对于计算机网络通信来说,我需要用一个端口号来确定跟对方的哪个端口建立连接,需要用一个IP地址来找到对方主机所在位置,还需要用MAC地址来确定跟对方所在位置的哪个主机进行通信。其中的端口号就是在TCP包头中确定的,那么我们的包头中前两个内容可以确定,即源端口号和目的端口号。分别填到我们刚刚的图中的哪个位置呢?要占用多大的空间呢?这个比较好记的方法就是,一般接触过网络方面知识的都会知道端口号最大为65535,即0-65535总共65536个端口号,65536216次方,即一个端口号要个它预留16位的空间才能支持这么多端口号,那么源端口和目的端口总共需要占32位,我们填到第一行,就如下图:

 

是这样有了目的端口号和源端口号我们就可以组成一个包头,然后把这个包头加在数据包前面就可以交付下一层,然后这个数据包就可以肆无忌惮地遨游在互联网上了吗?当然不是啦~这样未免太简单粗暴而且不安全了吧,试想一下如果我们的数据在向下层交付了之后这个数据包在网络上传播,万一在某一个节点我们的这个数据包出现了错误,接收的主机也要这样傻乎乎地接收这个数据包么?所以我们的TCP一定要有一些机制来保证接收端可以发现这样的错误同时向发送端重新请求这个数据。来,让我们慢慢再想,既然TCP是可靠的面向连接的,那么它一定有检错机制以及出错处理机制,就是前方发现收到的数据包出现错误了,我怎么请求重传?是要再重新请求整个数据包么?那如果我们的数据非常大怎么办?这样重传会造成网络堵塞的吧?但是实际环境中特别大的数据包也是很常见的,所以我们的TCP做了一个很明智的决定,就是我把数据包分段,这个段大小叫做“最大报文段长度(Maximum Segment Size,MSS(附1。(请先记住这个概念,我们之后再解释这个概念)先发送一段给接收方,接收方收到以后确认无误了,那他就跟发送方说我收到了这一个数据包,而且是正确的,所以请你把下一段也发给我吧。那么TCP有一个机制就是发送一段然后确认一段,这样的话接收方收到的数据肯定是准确无误的,那么为了实现这个技术,我们要做哪些工作呢?

TCP 是面向字节流的,也就是在一个 TCP连接中传送的每一个字节流中每一个字节都是有编号的,如果我要给TCP数据包(即TCP报文的数据字段部分)分段的话肯定是把这个字节流分段,那么我在TCP包头中一定要有一个字段来表明当前的数据包中数据字段在整个大的数据包中的位置,怎么标记这个位置呢?最好的办法肯定是给字节流中的字节进行编号,然后用这个编号来标记这个字节的位置。那为了实现这个东西,我们可以在TCP的包头中增加一个选项,这个选项可以标记当前数据包中数据字段的第一个字节在整个大的数据包的字节流中的位置,这个选项我们称之为报文段序号。那么这个序号该定多少合适呢,其实呢,TCP可以一次性对4GB大小的数据进行分段,并不是不支持更大的数据格式,这个我们后面再说(附2)。4GB大小即232次方(这里要区分BByte,即字节)b(bit,位) )。我要描述一个大小为2^32字节的数据包,那么我最少要给这个“序号”字段预留32位的长度,那么我现在可以向刚刚的表格中再填一行数据,就像下面:


好了,这样我可以把报文段发送给接收方了,可是设想一下如果接收方接收到报文段了,他一看这个报文段是对的,怎么去告诉发送方我已经收到一个对的报文段了,那么请你把下一个报文段发给我呢?或者如果接收方收到数据包一看,哎呀妈呀,这个报文段不对啊,他开始懵逼了,他怎么告诉发送方他收到的报文段是错误的,而且他怎么要求发送方重传刚刚的数据包呢?这提醒我们要在刚刚的基础上再添加一些东西到我们的包头里。 

下节再写!

0 0
原创粉丝点击