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