Linux网络编程--wireshark分析TCP包头的格式
摘要:
本文简介了TCP面向连接理论知识,具体讲述了TCP报文各个字段含义。并从Wireshark俘获分组中选取TCP连接建立相关报文段进行分析。
一、概述
TCP是面向连接的可靠传输协议,两个进程互发数据之前须要建立连接,这里的连接仅仅只是是端系统中分配的一些缓存和状态变量,中间的分组交换机不维护不论什么连接状态信息。
连接建立整个步骤例如以下(即三次握手协议):
首先,客户机发送一个特殊的TCP报文段;
其次,server用还有一个特殊的TCP报文段来响应;
最后,客户机再用第三个特殊报文段作为响应。
图1 三次握手协议示意图[1]
二、TCP报文格式
2.1 概述
为了提供可靠的传输数据,TCP报文首部字段有较多的字段。TCP报文格式例如以下图:
图2 TCP报文格式
源和目标port
用于多路复用/多路分解来自或送至上层应用的数据。能够这样理解。port用来标识同一台计算机的不同进程。
序列号和确认号
这两个字段是TCP可靠传输服务的关键部分,序列号是该报文段首字节的字节流编号(TCP把数据看成是有序的字节流,TCP隐式地对数据流的每一个字节进行编号)。这样理解可能更直观,当报文被分解成多个报文段时。序列号就是报文段首字节在整个报文的偏移量。确定号指定下一个期待的字节。TCP是全双工的,如果从主机A接收到主机B的数据,则主机A填充进报文段的确认号是主机A期望从主机B收到的下一个字节序号。
还没理清这两者的关系?见下图(三次握手):
图3 正常情况下TCP连接建立过程
首部长度(4位)
由于选项是不定长的,这就须要标识整个首部字段的长度(单位是32位字),即5+选项个数。4位,单位是32位字,所以首部最长是15*4=60字节,即选项最长是40字节(10个选项)。
标志
URG
指示报文段里存在着被发送方的上层实体标记为"紧急"数据,当URG=1时,其后的紧急指针指示紧急数据在当前数据段中的位置(相对于当前序列号的字节偏移量),TCP接收方必须通知上层实体。
ACK
当ACK=0时,表示该数据段不包括确认信息。当ACK=1时。表示该报文段包括一个对已被成功接收报文段的确认。
PSH
当PSH=1时。接收方在收到数据后马上将数据交给上层,而不是直到整个缓冲区满。
RST
用于重置一个已经混乱的连接(如主崩溃),也可用于拒绝一个无效的数据段或者拒绝一个连接请求。一般而言,假设你得到的数据段被设置了RST位。那说明你这一端有问题了。
SYN
用于建立连接过程,在连接请求中。SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认。即SYN=1和ACK=1。
注:捎带是指对客户机到server数据的确认被装载在一个承载server到客户机的数据报文段中。
FIN
用于释放一个连接,表示发送方已经没有数据要传输了。
此时,接收方可能继续接收数据。好在SYN和FIN数据段都有序列号。从而保证了这两种数据段以正确顺序被处理。
窗体大小
用于流控制(确保连接的不论什么一方都不会过快地发送过量的分组而淹没还有一方),窗体大小指定了从被确认的字节算起能够发送多少个字节。
校验和
提供了额外可靠性。在计算检验和的时候,TCP的Checksum域设为0,假设数据域的字节数为奇数,则数据域填补一个额外的0字节。校验和算法:将全部的16位字按1的补码形式累加起来。取累加结果的补码。因此,当接收方运行相同计算时(包含Checksum域),结果应该是0。
紧急指针
參考标志字段的URG位。
选项
选项部分是为了适合复杂网络环境和更好地服务于应用层设计的。
TCP选项最长是40字节。详情见2.2。
数据
无不论什么数据的TCP段也是合法的。通经常使用于确认和控制信息。
2.2 选项字段[2]
TCP选项部分非常好出如今已经建立连接的会话中。仅仅要出如今TCP连接建立阶段,即三次握手。TCP选项部分实际运用有下面几种:
(1)最大报文传输段(MMS, Maximum Segment Size)
用于发送发与接收方协商最大报文段长度(不过净荷数据,不包含TCP首部字段)。TCP在三次握手中,每一方都会通告期望收到的MSS(MSS只出如今SYN数据包中),假设一方不接受还有一方的MSS值,则使用默认的536字节净荷数据,即主机可以接受20+536字节的TCP报文段。
(2)窗体扩大选项(Window scaling)
TCP报文的窗体大小字段占16位。即最大值是65535,但随着时延和带宽比較大的通信产生(如卫星通信),须要更大的窗体满足性能和吞吐率。这就是窗体扩大选项存在的意义。样例见參考资料[2]。
Windows scaling占3个字节,最后一个字节是移位值(Shift count),即首部的窗体位数16向左移动,如移位值为14。则新的窗体最大值增大到65535*(2^14)。
窗体扩大选项是在TCP建立之初进行协商,假设已实现了窗体扩大。当不再须要扩大窗体时。发送移位值=0就能够恢复到原窗体大小。即65535。
(3)选择确认选项(SACK, Selective Acknowledgements)
考虑这样情况,主机A发送报文段12345,主机B收到135且报文无差错。SACK用来确保仅仅重传缺少的报文段,而不是重传全部报文段。
SACK选项须要2个功能字节。一个用来指明使用SACK选项(SACK Permission),还有一指明这个选项占多少字节。
那怎么形容丢失的报文段2。说明2的左右边界各自是1、3。TCP的数据报文是有字块边界的。而这样的边界是由序列号表示的。
最多能指明多少个字节块的边界信息呢?答案是4个。这是由于选项字段最大是40字节,去除2个功能字节。序列号是32位即4字节,而且须要左右边界。所以(40-2)/8 = 4。
(4)时间戳选项(timestamps)
时间戳选项用来计算往返时间RTT,发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方将该时间戳字段的值拷贝到确认报文中,当接收方收到确认报文,对照确认报文的时间戳(等于发送方发送报文段的时间戳)和如今的时钟,就可以算出RTT。
时间戳选项还可用于防止回绕序号PAWS。
序列号仅仅有32位,每2^32个序列号就会回绕(想想环形队列)。採用时间戳选项非常easy区分同样序列号的报文段。
(5)NOP(NO-Operation)
TCP的头部必须是4字节的倍数,而大多数选项不是4字节倍数。不足的用NOP填充。
除此之外,NOP也用于切割不同的选项数据,如窗体扩大选项和SACK之间使用NOP隔离(以下的实例将看到这一点)。
三、实例解析
3.1 概述
还是以訪问百度首页为例,首先用DNS协议将URL解析成IP地址,接着在客户机和server间建立TCP连接。用Wireshark俘获的分组例如以下图:
图4 Wireshark俘获建立TCP连接分组
你一看会认为有些奇怪,理论上应该是3个分组的,怎么有6个分组?先不急。先把这6个报文收发示意图作出来(结合时间和报文含义),例如以下:
图5 TCP连接建立实例
从图可知,连接建立伊始。客户机发了两个报文段。这或许是为了更快建立连接(如果有个请求报文段丢失。也不至于要等一段时间,重发报文)。接下来。以19、21、22(上图红色线条所看到的)分析TCP连接建立过程。
3.1 第一次握手19
Wireshark俘获TCP连接第一次握手的报文段例如以下:
图6 TCP连接第一次握手实例
这里主要挑几个字段分析:
标志字段。SYN=1、ACK=0表示该数据段没有使用捎带的确认域。
最大报文段长度(MMS)1460是怎么来的。链路层的以太网物理特性决定数据帧长度为1500(即MTU,最大传输单元),1460=1500-20(IP首部长度)-20(TCP首部长度)。不要被该报文首部长度32字节所迷惑,这仅仅是建立连接过程。MSS与MTU关系见下图[2]:
图7 MSS与MTU关系
NOP字段。能够作为不足4倍数字节填充,也可作为选项间分隔,该报文段出现了3个NOP,详细功能见下图:
图8 TCP报文NOP字段
3.3 第二次握手21
server响应clientTCP报文段,此时确认号为1了。SYN=1、ACK=1表明连接应答捎带一个确认,Wireshark俘获分组例如以下:
图9 TCP连接第二次握手实例
为什么MSS是1452而不是1460?
这是由于使用PPPoE(Point-to-Point over Ethernet。能够使以太网的主机通过一个简单的桥接设备连到一个无端的接入集中器上[3])拨号上网。PPoP首部是8个字节,所以PPPoE的MTU是1492,MSS也就为1492-40=1452。
那么,TCP连接建立后传输数据的MSS是多少呢,1460 or 1452 or 536 ?我的理解是默认值536,这样理解对吗?求指点!
3.4 第三次握手22
客户机再次server的报文段,此时序列号和确认号都为1。没有选项字段,Wireshark俘获的分组信息例如以下:
图10 TCP连接第三次握手实例
值得注意的。由于窗体扩展大小协商未果,所以就不扩大窗体了,即窗体大小最大为65535。
如此,TCP连接建立:-)
Linux网络编程--wireshark分析TCP包头的格式的更多相关文章
- Linux网络编程案例分析
本代码来自于博主:辉夜星辰 本篇主要对运行代码中出现的问题进行分析,代码本身的内容后续展开讨论. 服务器端代码 /* Linux网络编程之TCP编程,服务器端读数据 socket函数之后,返回值ser ...
- Linux网络编程:基于TCP的程序开发回顾篇《转》
面向连接的TCP程序设计 基于TCP的程序开发分为服务器端和客户端两部分,常见的核心步骤和流程: 其实按照上面这个流程调用系统API确实可以完全实现应用层程序的开发,一点问题没有.可随着时间的推移,你 ...
- 【深入浅出Linux网络编程】 “实践 -- TCP & UDP”
通过上一篇博客的学习,你应该对基于epoll的事件触发机制有所掌握,并且通过阅读sio.c/sio.h应该也学会了如何封装epoll以及如何通过设计令epoll更加实用(用户回调,用户参数). 简单回 ...
- Linux网络编程——浅谈 TCP 三次握手和四次挥手
一.tcp协议格式 二.三次握手 在 TCP/IP 协议中.TCP 协议提供可靠的连接服务,採用三次握手建立一个连接. 第一次握手:建立连接时,client发送 syn 包(tcp协议中syn位置1. ...
- Linux网络编程二、tcp连接API
一.服务端 1.创建套接字: int socket(int domain, int type, int protocol); domain:指定协议族,通常选用AF_INET. type:指定sock ...
- Linux网络编程9——对TCP与UDP的简易封装2.0
具体生成动态库的操作及使用该动态库的操作请参见上篇博文.以下仅仅列出改进版本的代码. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #define __MY_SOCKE ...
- Linux网络编程8——对TCP与UDP的简易封装
引言 每次使用socket通信,都会有很对相似的操作.本文,会对TCP与UDP通信做一简单封装,并生成动态库. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #defi ...
- 【Linux 网络编程】常用TCP/IP网络编程函数
(1)函数socket /**************************************************************** ** 功能:创建一个套接字用于通信 ** 参 ...
- Linux网络编程7——使用TCP实现双方聊天
思路 主线程负责发送消息,另一线程负责接收消息.服务端和客户端均是如此. 注意 当A方close掉用于通信的socket端口后,该端口是不会立即关闭的.因为此时可能B方的信息还没send完.因此,此时 ...
随机推荐
- 介绍一款好用 mongodb 可视化工具
最近想自己搭建一个个人博客,所以学了下mongodb,mongodb是用命令行输入的,有些人可能不太习惯,我自己找了下mongodb的一些可视化工具,一开始安装的是mongoVUE,mongoVUE页 ...
- linux 更新源miss问题
1.之前新装的linuxMint 执行 apt-get install vim 安装失败 发现原因是源更新失败导致,后来执行apt-get update 发现老是获取失败,查了google总结出以下解 ...
- Node做中转服务器,转发接口
查询各种资料,和整理网上一哥们不完整的接口.做成,可以使用的转发服务! 由于项目在做前后端分离,牵扯跨域和夸协议问题,临时抱佛脚,选择用nodejs做中转,我想应该好多人都用它.但是做普通的表单转发没 ...
- SQL Server多表同时查询
今天在练sql server发现多条语句同时使用可以多表同时查询,具体操作如下: 代码示例: USE teachingGOSELECT *FROM dbo.teach_classORDER BY cl ...
- asp.net web api 版本控制
版本控制 版本控制的方法有很多,这里提供一种将Odata与普通web api版本控制机制统一的方法,但也可以单独控制,整合控制与单独控制主要的不同是:整合控制通过VersionController ...
- [转载] 十五分钟介绍 Redis数据结构
转载自http://blog.nosqlfan.com/html/3202.html?ref=rediszt Redis是一种面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存 ...
- shell脚本 expect 实现自动登陆
vi auto_ssh.exp #!/usr/bin/expect set ipaddress "123.227.159.159" set passwd "你的密码& ...
- vue+node+webpack搭建环境
一.环境搭建 1.1.去官网安装node.js( http://www.runoob.com/nodejs/nodejs-install-setup.html ) 注意node的版本,只有支持和谐模 ...
- PHP+Redis 实例【一】点赞 + 热度 上篇
这次的开篇,算是总结下这段时间来的积累吧,废话不多说,直接干! 前言 点赞其实是一个很有意思的功能.基本的设计思路有大致两种, 一种自然是用mysql(写了几百行的代码都还没写完,有毒)啦 数据库直接 ...
- java并发包下的并发工具类
1.Exchanger 功能:用于线程间数据的交换 应用场景:1)遗传算法,目前还不是特别理解 2)校对工作,假设A,B线程做同一件任务,可以通过数据校验判断两线程是否正确的工作 例子:是一个简单的 ...