• 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. 七个结构模式之桥接模式(Bridge Pattern)

    问题: 当存在多个独立的变化维度时,如果仍采用多层继承结构,会急剧的增加类的个数,因此可以考虑将各个维度分类,使他们不相互影响. 定义: 将抽象部分与它的实现部分进行分离,抽象部分只保留最为本质的部分 ...

  2. get()和post()方法编码的区别

    在做ssh搭建的框架中,在后台条件查询的时候,组合查询传到后台的值一直是乱码,其中在form表单中必须要加上method,这一点是肯定的,但是加上了提交的方式之后,会出现如下问题: 如果使用get方法 ...

  3. ScrollMagic – 酷毙了!超炫的页面滚动交互效果

    ScrollMagic 是一款 jQuery 插件,它让你可以像使用进度条一样使用滚动条.如果你想在特定的滚动位置开始一个动画,并且让动画同步滚动条的动作,或者把元素粘在一个特定的滚动位置,那么这款插 ...

  4. 小白的CSS基础学习

    CSS定义: CSS全称为“层叠样式表 (Cascading Style Sheets)”,它主要是用于定义HTML内容在浏览器内的显示样式. CSS代码语法: css样式选择组成部分:选择符+声明( ...

  5. 苹果浏览器和uc浏览器在移动端的坑(日常积累,随时更新)

    先mark 1 .  移动端uc浏览器不兼容css3 calc() 2 .  ie8下a标签没有内容给宽高也不能触发点击跳转 3 . safari输入框加上readOnly="ture&qu ...

  6. [deviceone开发]-echart的简单报表示例

    一.简介 echart是一个常用的基于h5的报表库.这个例子简单展示了实现折线图,柱状图,圆环图和圆饼图的使用. 并实现和do的非html部分的数据交互. 二.效果图 三.相关下载 https://g ...

  7. 用JS描述的数据结构及算法表示——栈和队列(基础版)

    前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里 ...

  8. 程序新能优化-SQL优化

  9. charset的获取方法

      1.解析http请求的返回值: 2.通过解析html的meta标签里面的数据: 3.通过cpdetector(java环境下)来自动验证: ---------------------------- ...

  10. Ioc容器Autofac系列(1)-- 初窥

     一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...