http://blog.csdn.net/c0c0cf/article/details/8677768
最初A,B主机都处于CLOSE状态。
B的TCP服务器进程先创建传输控制块TCB,准备接受客户端进程的连接请求。然后服务器进程就处于LISTEN状态,等待客户的连接请求,如有,即做出响应。
A的TCP客户端进程也首先创建传输控制块TCB,然后向B发出连接请求报文,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗一个序号。这时TCP客户端进入SYN-SEND(同步以发送)状态。
B收到连接请求报文后,如同意建立连接,则向A发送确认。在确认报文中应把SYN位和ACK位都置1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。
这个报文段不能携带数据,但同样消耗一个序号(因为它也发送了一个SYN报文)。这时TCP服务器进程进入SYN-RECV(同步状态)
TCP客户端进程收到B的确认后,还要向B给出确认,确认报文的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报段的序号仍是seq=x+1。这时TCP连接已经建立,A进入ESTABLISHED状态。B收到A的确认后,也进入ESTABLISTEND状态。
上面的过程叫做三次握手·!!
确认ack:仅当ack=1时确认序号字段才有效,当ack=0时,确认序号无效。TCP规定,在连接建立后所传的送报文段都必须把ack置1。
同步syn:在建立连接时用来同步序号,当syn=1而ack=0时,表明这时一个连接请求报文,因此syn置为1就表示这时一个请求连接或连接接受报文
===================
连接的建立
在TCP协议与"流"通信中讨论的TCP传输需要一个前提:TCP连接已经建立。然而,TCP连接从无到有需要一个建立连接的过程。建立连接的最重要目是让连接的双方交换初始序号(ISN, Initial Sequence Number)。根据TCP协议的规定,文本流的第一个片段的序号不能是确定的数字(比如说1)。连接的双方各自随机生成自己的ISN,然后再利用的一定方式让对方了解。这样的规定是出于TCP连接安全考虑:如果以一个确定的数字作为初始的TCP序号,那么其他人很容易猜出接下来的序列号,并按照正确的序号发送“伪装”的TCP片段,以插入到文本流中。
ISN交换是通过SYN片段实现的。SYN片段由头部的SYN位表明,它的序号为发送方的ISN。该片段由连接的一方首先发给给另一方,我们将发送SYN的一方称为客户(client),而接收SYN的一方称为服务器(server)。我们使用ISN(c)表示client一方的ISN,使用ISN(s)表示server一方的ISN。(即双方的seq number互不干扰)随后,接收到SYN的server需要回复ACK,并发送出包含有server的ISN的SYN片段。下图为建立连接的过程,也就是经典的TCP三次握手(three-way handshaking)。两条竖直线分别为client和server的时间轴。每个箭头代表了一次TCP片段的单向传输。
青色为纯粹的ACK片段。整个过程的本质是双方互发含有自己的ISN的SYN片段。根据TCP传输的规则,接收到ISN的一方需要回复ACK,所以共计四片信息在建立连接过程中传输。之所以是三次握手 (而不是四次),是因为server将发送SYN和回复ACK合并到一个TCP片段中。我们以client方为例。client知道自己的ISN(也就是ISN(c))。建立连接之后,它也知道了对方的ISN(s)。此后,如果需要发送文本流片段,则编号为ISN(c) + 1, ISN(c) + 2 ...。如果接收文本流片段,则期待接收ISN(s) + 1, ISN(s) + 2 ...。
连接建立之后,连接的双方就可以按照TCP传输的方式相互发送文本流了。
============
序号(sequence number for a segment):TCP把数据看成是一个无结构的但是有序的字节流。序号是建立在传送的字节流之上而不是建立在传送的报文段的序列之上。假定数据流由一个500 000字节的文件组成,MSS为1000个字节,数据流的首字节编号是0。TCP为该数据流建500个报文段。第一个报文段序号为0,第二个为1000,第三个为2000,以此类推。
确认号:假定接收端成功接收到了对方发来的序号X,它就把确认号定义为X+1。
+++++++++++++
TCP 的数据流
TCP的数据流大致可以分为两类,交互数据流与成块的数据流。交互数据流就是发送控制命令的数据流,比如relogin,telnet,ftp命令等等;成块数据流是用来发送数据的包,网络上大部分的TCP包都是这种包。 很明显,TCP在传输这两种类型的包时的效率是不一样的,因此为了提高TCP的传输效率,应该对这两种类型的包采用不同的算法。
TCP的PUSH包
http://blog.csdn.net/ce123_zhouwei/article/details/9038365
PUSH是TCP报头中的一个标志位,发送方在发送数据的时候可以设置这个标志位。该标志通知接收方将接收到的数据全部提交给接收进程。这里所说的数据包括与此PUSH包一起传输的数据以及之前就为该进程传输过来的数据。
当Server端收到这些数据后,它需要立刻将这些数据提交给应用层进程,而不再等待是否还有额外的数据到达。
那么应该合适设置PUSH标志呢?实际上现在的TCP协议栈基本上都可以自行处理这个问题,而不是交给应用层处理。如果待发送的数据会清空发送缓存,那么栈就会自动为此包设置PUSH标志,源于BSD的栈一般都会这么做,而且,BSD TCP STACK也从来不会将收到的数据推迟提交给应用程序,因此,在BSD TCP STACK中,PUSH位是被忽略的,因为根本就没有用。