TCP学习笔记

TCP协议与其它协议之间的关系:

       +------+ +-----+ +-----+       +-----+                    
       |Telnet| | FTP | |Voice|  ...  |     |  Application Level 
       +------+ +-----+ +-----+       +-----+                    
             |   |         |             |                       
            +-----+     +-----+       +-----+                    
            | TCP |     | RTP |  ...  |     |  Host Level        
            +-----+     +-----+       +-----+                    
               |           |             |                       
            +-------------------------------+                    
            |    Internet Protocol & ICMP   |  Gateway Level     
            +-------------------------------+                    
                           |                                     
              +---------------------------+                      
              |   Local Network Protocol  |    Network Level     
              +---------------------------+   

 

TCP的流控制是通过在接收者发往发送者的ACK中TCP首部的window字段(接收窗口长度)来实现的:

    TCP provides a means for the receiver to govern the amount of data
    sent by the sender.  This is achieved by returning a "window" with
    every ACK indicating a range of acceptable sequence numbers beyond
    the last segment successfully received.  The window indicates an
    allowed number of octets that the sender may transmit before
    receiving further permission.

TCP具有超时重发的机制,如果在指定时间内没有接收到相应的ACK,那么相应的Segment将会重新发送。

可以同时打开多个SOCKET去监听同一个PORT, 那么TCP将首先匹配到指定外部SOCKET地址的TCB,然后再去匹配不指定外部SOCKET地址的TCB。

 

icmp可以用于获取另一台机器的时间,发送端在“发送时间戳”字段填入发送的时间,而接收端需要在“接收时间戳”字段写入接收到的时间并再次发回给发送端,这样子一来发送端就可以计算出从往返延迟了。另外RFC1307还描述了一种毫秒级的时间同步协议。

 

一个连接同时使用sourceIP destIP sourcePort destPort来唯一确定 。

 

为什么TCP需要3次握手而不是2次:

第一次在面试题里面看到这个问题,根RFC793上的说法,TCP其于IP(Internet Protocol)协议,IP协议是不可靠的,建立一个100%可靠的连接显然不可能。当然,如果连接足够可靠,那我们无须进行这个过程,或者我们可以将握手的次数增加到4次或者5次以得到一个更加稳定的连接),3次连接则是这样子的一个折中。可以避免大部分错误的情况,同时节省建立连接的消耗。

从另一个方面来说,让连接双方都相互“知道”彼此的ISN,那么至少进行3次握手,两次学习到其中一方的ISN。

因为握手过程中发送的SYN和ACK可能会迟到或者丢失,所以,在不稳定的网络环境中,两次握手是不恰当的,比如下面的过程,TCP发出ACK之后马上进入ESTABLISHED状态,并通知上层的应用程序,但步骤2中的ACK很可能会丢失。如果某个时候网络环境很糟糕,上层的应用则得到大量无效的连接,这是不恰当的。

    TCP A                                                 TCP B
    CLOSED                                                LISTEN
1: (SYN_SENT)        ---(SEQ=100,CTL=SYN) -->             (SYN_RECEIVED)
2: (ESTABLISHED)     <--(SEQ=300,ACK=101,CTL=ACK) --      (ESTABLISHED)
POSSIBILITY 1


TCP A TCP B
CLOSED LISTEN
1: (SYN_SENT) ---(SEQ=100,CTL=SYN) ... LISTEN
2: (SYN_SENT) ---(SEQ=110,CTL=SYN) ... LISTEN
3: ---(SEQ=100,CTL=SYN) --> (SYC_RECEIVED)
4: (ESTABLISHED) <--(SEQ=200,ACK=101,CTL=ACK) --- (ESTABLISHED)
5: ---(SEQ=110,CTL=SYN) --> (???)
POSSIBILITY 2

 

一些控制packet的segment length==1

Usually, TCP packets with a len of 1 are control packets (ACK,SYN,FIN,RST)

 

TCP连接断开的过程也比较麻烦,有四次握手的说法,但这种说法可以说不是很准确。

TCP A
CLOSE_WAIT_1 ---(SEQ=300,ACK=100,CTL=<FIN,ACK>) --> FIN_WAIT
CLOSE_WAIT_2 <--(SEQ=100,ACK=301,CTL=<ACK>) --- FIN_WAIT
TIME_WAIT <--(SEQ=xxx,ACK=301,CTL=<FIN,ACK>) --- LAST_ACK(Close)
TIME_WAIT ---(SEQ=301,ACK=101,CTL=<ACK>) --> CLOSED
2MSL(TIME_WAIT)
CLOSED

 

发送方接收到ACK时,在重发队列中所有的SEGMENT,如果SEG.SEQ + SEG.LEN <= ACK.SEQ,则这个SEGMENT被接收者确认(Acknowledged),并可以从队列中移出。

 

 今天同事做技术交流的时候带回来了一些问题:

1、三次握手完成之前是否需要accept操作,从上面的握手过程可以知道,只有三次握手完成之后,网络栈才会认为这个东西是正确的。然后才会交给应用进程去处理。

2、主进程和子进程之间共享socket文件描述符时候,比如nginx,三次握手的时候(中间过程),netstat的时候,这个连接是的进程号是谁的?其实这个现象是不确定的,比如centos平台上面,netstat的时候,进程号部分为-,即不知道这个连接归那个进程号所有。

3、linux平台上面只要拿到文件描述符就可以对socket进行accept,比如nginx的二进制文件升级的时候,用的就是这个特性。

 

其实这些东西都还是些linux 编程的东西,还是回去好好搞LINUX内核和LINUX平台上的编程?FUCK

posted on 2019-04-03 10:09  mosmith  阅读(164)  评论(0编辑  收藏  举报