• TCP包结构

  一个TCP包结构如下:

  一个TCP包主要由TCP包头和数据部分组成,包头固定部分为20字节,选项和数据部分根据实际情况设置为4N(N可以为0)字节。

  1.16bit源端口和目的端口号,它可以确认数据的传输方向(暂不考虑更底层的包)

  2.32bit序号,它是为TCP包中数据部分进行编号的部分。假设要发送的数据有100M,由于受MSS( Maximum Segment Size 最大报文段长度)限制,一个TCP包是不可能传输完这100M的数据,于是需要将数据拆分,为了确保拆分传输后的数据能在接收端正确的拼接,就需要对每个拆分的数据包进行编号来传输。这样,这个32位的序号指的就是本包数据部分第一个字节是这个100M数据中的第多少个字节。例如:假设发送第一个包时,先取出这100M数据的前面1024个字节发送,这时这个包中32位序号就是1,然后取下一个1024字节传输,这个时候的数据部分的第一个字节是这100M数据的第1025个字节,所以这第二TCP包中32位的序列号就应该为1025。当序号超过2^32时,进行一个轮回,重新从0开始计数。

  3.32bit确认序号,和上面的32位序号类似,只不过它指的是期望收到的下一个包的数据部分的编号。

  4.4bit首部长度,单位为4字节,指的是一个TCP包中除去数据部分的长度,也就是包头固定部分+选项部分的长度,2^4 -1 = 15, 15*4字节=60字节,即包头固定部分为20字节,选项最多可以为40字节。

  5.标识位:

    URG:.........

    ACK:TCP包的Acknowledgement number有效位,1时表明Acknowledgement number有效,0表示Acknowledgement number无效,忽略Acknowledgement number字段。自tcp连接建立后,ACK必须为1。

    PSH:TCP包中有数据需要尽快传递给应用层使用,而不是将数据进行缓冲,等到缓冲区满了再投递给应用层。

    RST:..........

    SYN:TCP包的同步位

    FIN:表示这个方向的带数据的包传输已经完成,即发送FIN包的端没有带数据的包过来了,需要释放这个方向的连接。

  • TCP三次握手

  TCP三次握手过程:

  

  测试代码,server端:

 #include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> #define ECHO "yes,i see you!" int main ( int argc, char *argv[] )
{
int ret,rn;
int socketfd,acfd;
int socklen;
char buf[]; struct sockaddr_in hostaddr;
struct sockaddr_in clientaddr; socketfd = socket(AF_INET, SOCK_STREAM, );
if ( socketfd < )
{
perror("socket");
return -;
} memset((void *)&hostaddr, , sizeof(hostaddr));
hostaddr.sin_family = AF_INET;
hostaddr.sin_port = htons();
hostaddr.sin_addr.s_addr = htonl(INADDR_ANY); ret = bind(socketfd, (struct sockaddr *)&hostaddr, sizeof(hostaddr));
if ( ret < )
{
perror("bind");
close(socketfd);
return -;
} ret = listen(socketfd, );
if ( ret < )
{
perror("listen");
close(socketfd);
return -;
} socklen = sizeof(struct sockaddr);
acfd = accept(socketfd, (struct sockaddr *)&clientaddr, &socklen);
if ( acfd < )
{
perror("accept");
close(socketfd);
return -;
} while ()
{
memset(buf, 0x0, sizeof(buf));
rn = read(acfd, buf, sizeof(buf));
printf("%s\n",buf);
}
//write(acfd, ECHO, sizeof(ECHO)); close(acfd);
close(socketfd); return ;
}

  client端:

 #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> #define HI "hi,can you see me?" int main ( int argc, char *argv[] )
{
int ret;
int socketfd,acfd;
int socklen;
struct sockaddr_in hostaddr;
char buf[]; socketfd = socket(AF_INET, SOCK_STREAM, );
if ( socketfd < )
{
perror("socket");
return -;
} memset((void *)&hostaddr, , sizeof(hostaddr));
hostaddr.sin_family = AF_INET;
hostaddr.sin_port = htons();
hostaddr.sin_addr.s_addr = htonl(INADDR_ANY); socklen = sizeof(struct sockaddr);
acfd = connect(socketfd, (struct sockaddr *)&hostaddr, sizeof(hostaddr));
if ( acfd < )
{
perror("connect");
close(socketfd);
return -;
} write(socketfd, HI, sizeof(HI)); //memset(buf, 0x0, sizeof(buf));
//read(socketfd, buf, sizeof(buf));
//printf("%s\n",buf); close(socketfd);
return ;
}

  这是CS间一对一的连接方式,各自完成一次收发。先运行server端,在accept下一行下断点,再运行client端,在connet的下一行下断点,使用wireshark抓包,过滤端口为6666的tcp包 tcp.port ==  ,运行,再断点处停下来时,可以看到抓到了3个包:

  这就是TCP三次握手的3个包,TCP的握手是发生在client端进行connect时。

  对于握手包的Sequence number和Acknowledgment number我理解为三次握手的包序。这里有RFC 793的解释:

  Sequence Number: 32 bits The sequence number of the first data octet in this segment (except when SYN is present). If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1.

  Acknowledgment Number: 32 bits If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent.

  第一次握手:

    client:"server,我要找你了!(SYN == 1),这是我第一次和你说话(Seq num == 0)" ,TCP包如下:

    可以看到Source port:33335,Destination port:6666,说明是C--->S这个方向传输的,Sequence为0,SYN被置位,没有数据部分。

  第二次握手:

    server:"client我听到你叫我了(ACK = = 1),你听到我的回应了吗(SYN == 1)?,这是我第一次和你说话(Seq num == 0),我等你第二次和我说话(Ack num == 1)",TCP包如下:

    可以看到Source port:6666,Destination port:33335,说明是S--->C这个方向传输的,Sequence num为0,Ack num为 1,SYN,ACK被置位,没有数据部分。

  第三次握手:

    clinet:"server,知道你听到我了(ACK ==  1),我们可以开聊了,这是我第二次和你说话(Seq num == 1),我等你和我第二次说话(Ack num == 1)"

    

    可以看到Source port:33335,Destination port:6666,说明是C--->S这个方向传输的,Sequence num为1,Ack num为 1,ACK被置位,没有数据部分。

  • 为什么要三次握手

  结合网上搜索,我觉得这是由于TCP是可靠的全双工的传输协议。首先,为什么要握手?因为需要确保可靠。为什么要3次,因为3次是理论上确保全双工握手成功的最少次数。对于单工,确保一次通信可以需要:1发送方把数据发送出去(SYN),2接收方回应发送方接收成功(ACK),这样形成了一个闭环。看看三次握手怎么做的:

  第一次: CLIENT----syn----->SERVER

  第二次: SERVER----ack,syn---->CLIENT

  第三次: CLIENT----ack----->SERVER

  这样,从client---->server, server---->client各自通过一次syn,ack形成闭环,理论上形成了一个近似可靠的通信。为什么说是近似可靠?因为完全可靠的通信是不存在的,见谢希仁<<计算机网络>>里面讲的红团蓝团问题。

  • TCP数据的传输

  握手成功后,开始传输第一个分节的数据,一次数据的传输需要2个TCP包。数据发送包,接收方应答包。

  1.Client---data--->Server:

  

  2.Server---ack--->Client

  • TCP的四次挥手

    四次挥手的时序

  一般来说,网络编程的CS模型中,服务端可以认为是一直不退出的,并且它是被动的一放,因此一般需要断开连接都是由客户端主动提出。

  类似于TCP的三次握手,四次挥手的四步:

    Client---fin,ack--->Server

    Server---ack---->Clinet

    Server---fin,ack--->Client

    Client----ack----->Server

  先把2次发送FIN的包中的ACK(未着色的)忽略,因为TCP建立连接后ACK必须置位。类似于三次握手的分析,一对FIN--ACK包的往来,形成一个闭环,保证了单侧通信的可靠。对比于三次握手,为什么不把四次挥手中间2个包合并呢?它们都是S-->C为什么要单独拆分来发送呢?注意到FIN的意义:表示这个方向的带数据的包传输已经完成,即发送FIN包的端没有带数据的包过来了,需要释放这个方向的连接。。那么接收到FIN包的这一方虽然不再接收对端的带数据的包,但是它仍然可以发带数据的包过去。

  以后补充

  http://blog.csdn.net/xifeijian/article/details/12777187

  http://blog.csdn.net/dog250/article/details/5747549

TCP三次握手,数据传输,四次挥手的更多相关文章

  1. 使用 tcpdump 抓包分析 TCP 三次握手、四次挥手与 TCP 状态转移

    目录 文章目录 目录 前文列表 TCP 协议 图示三次握手与四次挥手 抓包结果 抓包分析 TCP 三次握手 数据传输 四次挥手 TCP 端口状态转移 状态转移 前文列表 <常用 tcpdump ...

  2. 应聘复习基础笔记1:网络编程之TCP与UDP的优缺点,TCP三次握手、四次挥手、传输窗口控制、存在问题

    重要性:必考 一.TCP与UDP的优缺点 ①TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供 ...

  3. 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

    .引言 网络编程中TCP协议的三次握手和四次挥手的问题,在面试中是最为常见的知识点之一.很多读者都知道“三次”和“四次”,但是如果问深入一点,他们往往都无法作出准确回答. 本篇文章尝试使用动画图片的方 ...

  4. TCP‘三次握手’和‘四次挥手’(通俗易懂)

      概述 我们都知道 TCP 是 可靠的数据传输协议,UDP是不可靠传输,那么TCP它是怎么保证可靠传输的呢?那我们就不得不提 TCP 的三次握手和四次挥手. 三次握手 下图为三次握手的流程图 下面通 ...

  5. 【转】TCP三次握手和四次挥手全过程及为什么要三次握手解答

    TCP三次握手和四次挥手的全过程   TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位,有6种表示: SYN(synchronous建立连接) ...

  6. [ 转载 ] Tcp三次握手和四次挥手详解

    #TCP的报头: 源端口号:表示发送端端口号,字段长为16位.目标端口号:表示接收端口号,字段长为16位.序列号:表示发送数据的位置,字段长为32位.每发送一次数据,就累加一次该数据字节数的大小.注意 ...

  7. 网络协议-网络分层、TCP/UDP、TCP三次握手和四次挥手

    网络的五层划分是什么? 应用层,常见协议:HTTP.FTP 传输层,常见协议:TCP.UDP 网络层,常见协议:IP 链路层 物理层 TCP 和 UDP 的区别是什么 TCP/UDP 都属于传输层的协 ...

  8. TCP三次握手与四次挥手详解

    目录 TCP三次握手与四次挥手详解 1.TCP报文格式 2.TCP三次握手 3.TCP四次挥手 4.为什么建立连接需要三次握手? 5.为什么断开连接需要四次挥手? 6.为什么TIME_WAIT状态还需 ...

  9. [转帖]脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

    脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手   http://www.52im.net/thread-1729-1-1.html     1.引言 网络编程中TCP协议的三次握手和 ...

  10. 学习 TCP 三次握手和四次挥手

    TCP三次握手和四次挥手的问题在面试中是最为常见的考点之一.很多读者都知道三次和四次,但是如果问深入一点,他们往往都无法作出准确回答. 本篇尝试使用动画来对这个知识点进行讲解,期望读者们可以更加简单地 ...

随机推荐

  1. java RSA加解密以及用途

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...

  2. Hibernate(五)__hql语句

    hql(hibernate query language)功能强大. 首先回忆下之前我们接触的对数据对象的操作: ①删除session.delete(对象) ②保存session.save(对象)   ...

  3. Tsql查询执行顺序(二)

    来源:http://www.cnblogs.com/gaiyang/archive/2011/04/13/2014356.html T-SQL查询处理这种逻辑处理顺序,是理论上的处理过程,实际情况还会 ...

  4. sql with 递归 查询特定区间日期

    declare @startDay smalldatetime ='2013-01-01'  ;with cte as(     select @startDay as d    union all  ...

  5. github添加ssh key报错Key is invalid. Ensure you've copied the file correctly

    github添加ssh key的时候报错:Key is invalid. Ensure you've copied the file correctly 将秘钥复制粘贴到文本编辑器中,再粘贴复制到

  6. windows 80 端口占用

    1. cmd 2. regidit 3. 注册表 KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP'右边有一个'start'的DWORD ...

  7. 由Vue引发的getter和setter思考

    公司的新项目决定使用Vue.js来做,当我打印出Vue实例下的data对象里的属性时,发现了一个有趣的事情: 它的每个属性都有两个相对应的get和set方法,我觉的这是多此一举的,于是去网上查了查Vu ...

  8. iOS从info.plist获取项目的名称及版本号

    NSString *executableFile = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundl ...

  9. <转>关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系

    转自:http://www.cnblogs.com/cywin888/p/3263027.html 刚接触iOS开发的人难免会对苹果的各种证书.配置文件等不甚了解,可能你按照网上的教程一步一步的成功申 ...

  10. iOS开发之百度地图导航

    本篇主要讲述百度地图的导航功能: 第一步:在使用百度导航之前,我们需要在百度地图开放平台上下载导航的 SDK,共85.8M,网速不好的同学可提前准备好. 第二步:引入导航所需的系统包 将AudioTo ...