精华内容
下载资源
问答
  • tcp状态转移图

    2014-05-13 19:48:34
  • 详解TCP状态转移图

    千次阅读 2018-02-27 15:27:24
    根据TCP状态转移过程,可进行一步一步分析。 一般而言,TCP连接是由客户端发起,并通过三次握手建立连接(特殊情况是所谓同时打开)的。 TCP关闭过程相对复杂一些,可能是客户端执行主动关闭;也可能是服务器...

    这里写图片描述

    TCP连接是面向连接,可靠的数据流服务。根据TCP状态转移过程图,可进行一步一步分析。
    一般而言,TCP连接是由客户端发起,并通过三次握手建立连接(特殊情况是所谓同时打开)的。
    TCP关闭过程相对复杂一些,可能是客户端执行主动关闭;也可能是服务器执行主动关闭,比如服务器程序被中断而强制关闭连接;还可能是同时关闭(比较少见)。

    首先我们来看一下TCP连接的连接和关闭。

    这里写图片描述

    三次握手:

    (1)客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。

    (2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。

    (3) 客户必须再次回应服务段一个ACK报文,这是报文段3。

    客户端通过connect系统调用主动与服务器建立连接。connect系统调用首先给服务器发送一个同步报文段,使连接转移到SYN_SENT状态。此后,connect系统调用可能因为如下两个原因失败返回:

    • 如果connect连接的目标端口不存在,或者该端口仍被处于TIME_WAIT状态的连接占用,则服务器将给客户端发送一个复位报文段,connect调用失败。
    • 如果目标端口存在,但connect在超时时间内未收到服务器的确认报文段,则connect调用失败。

    四次挥手:

    TCP连接是全双工通信,因此每个方向需要单独关闭。

    1. FIN_WAIT_1:第一次挥手。主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送FIN 给对方,然后等待对方返回 ACK 。调用 close() 第一次挥手就进入此状态。
    2. CLOSE_WAIT:接收到FIN之后,被动关闭的一方进入此状态。具体动作是接收到 FIN,同时发送 ACK。之所以叫 CLOSE_WAIT可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。
    3. FIN_WAIT_2:主动端(这里是客户端)先执行主动关闭发送FIN,然后接收到被动方返回的 ACK 后进入此状态。
    4. LAST_ACK:被动方(服务器端)发起关闭请求,由状态2 进入此状态,具体动作是发送 FIN给对方,同时在接收到ACK时进入CLOSED状态。
    5. CLOSING:两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1
      进入此状态,等待被动方返回ACK。
    6. TIME_WAIT:从状态变迁图会看到,四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入该状态

    • 由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到。
    • 由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方(服务器端)也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序。
    • 由FIN_WAIT_2进入:这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应 ACK。

    半关闭状态:

    (TCP通信是半双工的)通信的一端可以发送结束报文段给对方,告诉它本端已经完成数据的发送,但允许继续接收来自对方的数据,知道对方发送结束报文段以关闭连接。
    这里写图片描述

    服务器和客户端判断对方是否关闭连接的方法是:read系统调用返回0(收到结束报文段)

    TIME_WAIT状态

    存在意义:

    • 可靠地终止TCP连接。
    • 保证让迟来的TCP报文段有足够的时间被识别并丢弃。

    TIME_WAIT状态要持续2MSL时间的原因:

    因为TCP报文段的最大生存时间是MSL,所以坚持2MSL时间能过确保网络上两个传输方向上尚未被接收
    到的,迟到的TCP报文段被中专路由器丢弃。
    

    TIME_WAIT和CLOSE_WAIT区别:

    • CLOSE_WAIT是被动关闭的一端在接收到对端关闭请求(FIN报文段)并且将ACK发送出去后所处的状态,这种状态表示:收到了对端关闭的请求,但是本端还没有完成工作,还未关闭。

    • TIME_WAIT状态是主动关闭的一端在本端已经关闭的前期下,收到对端的关闭请求(FIN报文段)并且将ACK发送出去后所处的状态,这种状态表示:双方都已经完成工作,只是为了确保迟来的数据报能被是被并丢弃,可靠的终止TCP连接。

    • -

    同时打开——”四次握手“

    客户端和服务器同时互发请求SYN,回复ACK确认报文段。
    这里写图片描述

    同时关闭——“三次挥手”

    服务器回复ACK和确认FIN同时发送,客户端刚好没其他事务处理。
    这里写图片描述

    参考资料:《Linux高性能服务器编程》
    博客:http://blog.csdn.net/wenqian1991/article/details/40110703

    展开全文
  • TCP状态转移的原理并不高深,但是处理逻辑比较复杂,以下是TCP状态转移图。出自《TCP/IP协议详解:卷2》——W.Richard Stevens 这些状态是怎么实现的呢? 我们来看一下内核源代码。(server端部分)  ...

    本文原创为freas_1990,转载请标明出处http://blog.csdn.net/freas_1990/article/details/10223581

    TCP状态转移的原理并不高深,但是处理逻辑比较复杂,以下是TCP状态转移图。出自《TCP/IP协议详解:卷2》——W.Richard Stevens


    这些状态是怎么实现的呢?

    我们来看一下内核源代码。(server端部分)

     

    int
    tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
    	unsigned long daddr, unsigned short len,
    	unsigned long saddr, int redo, struct inet_protocol * protocol)
    {
      struct tcphdr *th;
      struct sock *sk;
    
      if (!skb) {
    	DPRINTF((DBG_TCP, "tcp.c: tcp_rcv skb = NULL\n"));
    	return(0);
      }
    #if 0	/* FIXME: it's ok for protocol to be NULL */
      if (!protocol) {
    	DPRINTF((DBG_TCP, "tcp.c: tcp_rcv protocol = NULL\n"));
    	return(0);
      }
    
      if (!opt) {	/* FIXME: it's ok for opt to be NULL */
    	DPRINTF((DBG_TCP, "tcp.c: tcp_rcv opt = NULL\n"));
      }
    #endif
      if (!dev) {
    	DPRINTF((DBG_TCP, "tcp.c: tcp_rcv dev = NULL\n"));
    	return(0);
      }
      th = skb->h.th;
    
      /* Find the socket. */
      sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
      DPRINTF((DBG_TCP, "<<\n"));
      DPRINTF((DBG_TCP, "len = %d, redo = %d, skb=%X\n", len, redo, skb));
      
      /* If this socket has got a reset its to all intents and purposes 
         really dead */
      if (sk!=NULL && sk->zapped)
    	sk=NULL;
    
      if (sk) {
    	 DPRINTF((DBG_TCP, "sk = %X:\n", sk));
      }
    
      if (!redo) {
    	if (tcp_check(th, len, saddr, daddr )) {
    		skb->sk = NULL;
    		DPRINTF((DBG_TCP, "packet dropped with bad checksum.\n"));
    if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n");
    		kfree_skb(skb,FREE_READ);
    		/*
    		 * We don't release the socket because it was
    		 * never marked in use.
    		 */
    		return(0);
    	}
    
    	th->seq = ntohl(th->seq);
    
    	/* See if we know about the socket. */
    	if (sk == NULL) {
    		if (!th->rst)
    			tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
    		skb->sk = NULL;
    		kfree_skb(skb, FREE_READ);
    		return(0);
    	}
    
    	skb->len = len;
    	skb->sk = sk;
    	skb->acked = 0;
    	skb->used = 0;
    	skb->free = 0;
    	skb->saddr = daddr;
    	skb->daddr = saddr;
    
    	/* We may need to add it to the backlog here. */
    	cli();
    	if (sk->inuse) {
    		if (sk->back_log == NULL) {
    			sk->back_log = skb;
    			skb->next = skb;
    			skb->prev = skb;
    		} else {
    			skb->next = sk->back_log;
    			skb->prev = sk->back_log->prev;
    			skb->prev->next = skb;
    			skb->next->prev = skb;
    		}
    		sti();
    		return(0);
    	}
    	sk->inuse = 1;
    	sti();
      } else {
    	if (!sk) {
    		DPRINTF((DBG_TCP, "tcp.c: tcp_rcv bug sk=NULL redo = 1\n"));
    		return(0);
    	}
      }
    
      if (!sk->prot) {
    	DPRINTF((DBG_TCP, "tcp.c: tcp_rcv sk->prot = NULL \n"));
    	return(0);
      }
    
      /* Charge the memory to the socket. */
      if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) {
    	skb->sk = NULL;
    	DPRINTF((DBG_TCP, "dropping packet due to lack of buffer space.\n"));
    	kfree_skb(skb, FREE_READ);
    	release_sock(sk);
    	return(0);
      }
      sk->rmem_alloc += skb->mem_len;
    
      DPRINTF((DBG_TCP, "About to do switch.\n"));
    
      /* Now deal with it. */
      switch(sk->state) {
    	/*
    	 * This should close the system down if it's waiting
    	 * for an ack that is never going to be sent.
    	 */
    	case TCP_LAST_ACK:
    		if (th->rst) {
    			sk->zapped=1;
    			sk->err = ECONNRESET;
     			sk->state = TCP_CLOSE;
    			sk->shutdown = SHUTDOWN_MASK;
    			if (!sk->dead) {
    				sk->state_change(sk);
    			}
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    	case TCP_ESTABLISHED:
    	case TCP_CLOSE_WAIT:
    	case TCP_FIN_WAIT1:
    	case TCP_FIN_WAIT2:
    	case TCP_TIME_WAIT:
    		if (!tcp_sequence(sk, th, len, opt, saddr,dev)) {
    if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: not in seq\n");
    #ifdef undef
    /* nice idea, but tcp_sequence already does this.  Maybe it shouldn't?? */
    			if(!th->rst)
    				tcp_send_ack(sk->sent_seq, sk->acked_seq, 
    				     sk, th, saddr);
    #endif
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (th->rst) {
    			sk->zapped=1;
    			/* This means the thing should really be closed. */
    			sk->err = ECONNRESET;
    
    			if (sk->state == TCP_CLOSE_WAIT) {
    				sk->err = EPIPE;
    			}
    
    			/*
    			 * A reset with a fin just means that
    			 * the data was not all read.
    			 */
    			sk->state = TCP_CLOSE;
    			sk->shutdown = SHUTDOWN_MASK;
    			if (!sk->dead) {
    				sk->state_change(sk);
    			}
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    		if (
    #if 0
    		if ((opt && (opt->security != 0 ||
    			    opt->compartment != 0)) || 
    #endif
    				 th->syn) {
    			sk->err = ECONNRESET;
    			sk->state = TCP_CLOSE;
    			sk->shutdown = SHUTDOWN_MASK;
    			tcp_reset(daddr, saddr,  th, sk->prot, opt,dev, sk->ip_tos,sk->ip_ttl);
    			if (!sk->dead) {
    				sk->state_change(sk);
    			}
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (th->ack && !tcp_ack(sk, th, saddr, len)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (tcp_urg(sk, th, saddr, len)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (tcp_data(skb, sk, saddr, len)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		/* Moved: you must do data then fin bit */
    		if (th->fin && tcp_fin(sk, th, saddr, dev)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		release_sock(sk);
    		return(0);
    
    	case TCP_CLOSE:
    		if (sk->dead || sk->daddr) {
    			DPRINTF((DBG_TCP, "packet received for closed,dead socket\n"));
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (!th->rst) {
    			if (!th->ack)
    				th->ack_seq = 0;
    			tcp_reset(daddr, saddr, th, sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
    		}
    		kfree_skb(skb, FREE_READ);
    		release_sock(sk);
    		return(0);
    
    	case TCP_LISTEN:
    		if (th->rst) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    		if (th->ack) {
    			tcp_reset(daddr, saddr, th, sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (th->syn) {
    #if 0
    			if (opt->security != 0 || opt->compartment != 0) {
    				tcp_reset(daddr, saddr, th, prot, opt,dev);
    				release_sock(sk);
    				return(0);
    			}
    #endif
    
    			/*
    			 * Now we just put the whole thing including
    			 * the header and saddr, and protocol pointer
    			 * into the buffer.  We can't respond until the
    			 * user tells us to accept the connection.
    			 */
    			tcp_conn_request(sk, skb, daddr, saddr, opt, dev);
    			release_sock(sk);
    			return(0);
    		}
    
    		kfree_skb(skb, FREE_READ);
    		release_sock(sk);
    		return(0);
    
    	default:
    		if (!tcp_sequence(sk, th, len, opt, saddr,dev)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    	case TCP_SYN_SENT:
    		if (th->rst) {
    			sk->err = ECONNREFUSED;
    			sk->state = TCP_CLOSE;
    			sk->shutdown = SHUTDOWN_MASK;
    			sk->zapped = 1;
    			if (!sk->dead) {
    				sk->state_change(sk);
    			}
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    #if 0
    		if (opt->security != 0 || opt->compartment != 0) {
    			sk->err = ECONNRESET;
    			sk->state = TCP_CLOSE;
    			sk->shutdown = SHUTDOWN_MASK;
    			tcp_reset(daddr, saddr,  th, sk->prot, opt, dev);
    			if (!sk->dead) {
    				wake_up_interruptible(sk->sleep);
    			}
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    #endif
    		if (!th->ack) {
    			if (th->syn) {
    				sk->state = TCP_SYN_RECV;
    			}
    
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		switch(sk->state) {
    			case TCP_SYN_SENT:
    				if (!tcp_ack(sk, th, saddr, len)) {
    					tcp_reset(daddr, saddr, th,
    							sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
    					kfree_skb(skb, FREE_READ);
    					release_sock(sk);
    					return(0);
    				}
    
    				/*
    				 * If the syn bit is also set, switch to
    				 * tcp_syn_recv, and then to established.
    				 */
    				if (!th->syn) {
    					kfree_skb(skb, FREE_READ);
    					release_sock(sk);
    					return(0);
    				}
    
    				/* Ack the syn and fall through. */
    				sk->acked_seq = th->seq+1;
    				sk->fin_seq = th->seq;
    				tcp_send_ack(sk->sent_seq, th->seq+1,
    							sk, th, sk->daddr);
    	
    			case TCP_SYN_RECV:
    				if (!tcp_ack(sk, th, saddr, len)) {
    					tcp_reset(daddr, saddr, th,
    							sk->prot, opt, dev,sk->ip_tos,sk->ip_ttl);
    					kfree_skb(skb, FREE_READ);
    					release_sock(sk);
    					return(0);
    				}
    				sk->state = TCP_ESTABLISHED;
    
    				/*
    				 * Now we need to finish filling out
    				 * some of the tcp header.
    				 */
    				/* We need to check for mtu info. */
    				tcp_options(sk, th);
    				sk->dummy_th.dest = th->source;
    				sk->copied_seq = sk->acked_seq-1;
    				if (!sk->dead) {
    					sk->state_change(sk);
    				}
    
    				/*
    				 * We've already processed his first
    				 * ack.  In just about all cases that
    				 * will have set max_window.  This is
    				 * to protect us against the possibility
    				 * that the initial window he sent was 0.
    				 * This must occur after tcp_options, which
    				 * sets sk->mtu.
    				 */
    				if (sk->max_window == 0) {
    				  sk->max_window = 32;
    				  sk->mss = min(sk->max_window, sk->mtu);
    				}
    
    				/*
    				 * Now process the rest like we were
    				 * already in the established state.
    				 */
    				if (th->urg) {
    					if (tcp_urg(sk, th, saddr, len)) { 
    						kfree_skb(skb, FREE_READ);
    						release_sock(sk);
    						return(0);
    					}
    			}
    			if (tcp_data(skb, sk, saddr, len))
    						kfree_skb(skb, FREE_READ);
    
    			if (th->fin) tcp_fin(sk, th, saddr, dev);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (th->urg) {
    			if (tcp_urg(sk, th, saddr, len)) {
    				kfree_skb(skb, FREE_READ);
    				release_sock(sk);
    				return(0);
    			}
    		}
    
    		if (tcp_data(skb, sk, saddr, len)) {
    			kfree_skb(skb, FREE_READ);
    			release_sock(sk);
    			return(0);
    		}
    
    		if (!th->fin) {
    			release_sock(sk);
    			return(0);
    		}
    		tcp_fin(sk, th, saddr, dev);
    		release_sock(sk);
    		return(0);
    	}
    }


     





     

    展开全文
  • TCP状态转移图学习总结 (转)

    千次阅读 2012-09-28 22:08:00
    TCP状态转移图学习总结 (转) 这是网络编程的基础,tcp的状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析: 1.CLOSED:起始点...

    TCP状态转移图学习总结 (转)

    这是网络编程的基础,tcp的状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析:

    090310142823

    1.CLOSED:起始点,在超时或者连接关闭时候进入此状态。

    2.LISTEN:svr端在等待连接过来时候的状态,svr端为此要调用socket, bind,listen函数,就能进入此状态。此称为应用程序被动打开(等待客户端来连接)。

    3.SYN_SENT:客户端发起连接,发送SYN给服务器端。如果服务器端不能连接,则直接进入CLOSED状态。

    4.SYN_RCVD:跟3对应,服务器端接受客户端的SYN请求,服务器端由LISTEN状态进入SYN_RCVD状态。同时服务器端要回应一个ACK,同时发送一个SYN给客户端;另外一种情况,客户端在发起SYN的同时接收到服务器端得SYN请求,客户端就会由SYN_SENT到SYN_RCVD状态。

    5.ESTABLISHED:服务器端和客户端在完成3次握手进入状态,说明已经可以开始传输数据了。

    以上是建立连接时服务器端和客户端产生的状态转移说明。相对来说比较简单明了,如果你对三次握手比较熟悉,建立连接时的状态转移还是很容易理解。

    接下来服务器端和客户端就进行数据传输。。。。,当然,里面也大有学问,就此打住,稍后再表。

    下面,我们来看看连接关闭时候的状态转移说明,关闭需要进行4次双方的交互,还包括要处理一些善后工作(TIME_WAIT状态),注意,这里主动关闭的一方或被动关闭的一方不是指特指服务器端或者客户端,是相对于谁先发起关闭请求来说的:

    6.FIN_WAIT_1:主动关闭的一方,由状态5进入此状态。具体的动作时发送FIN给对方。

    7.FIN_WAIT_2:主动关闭的一方,接收到对方的FIN ACK,进入此状态。由此不能再接收对方的数据。但是能够向对方发送数据。

    8.CLOSE_WAIT:接收到FIN以后,被动关闭的一方进入此状态。具体动作时接收到FIN,同时发送ACK。

    9.LAST_ACK:被动关闭的一方,发起关闭请求,由状态8进入此状态。具体动作时发送FIN给对方,同时在接收到ACK时进入CLOSED状态。

    10.CLOSING:两边同时发起关闭请求时,会由FIN_WAIT_1进入此状态。具体动作是,接收到FIN请求,同时响应一个ACK。

    11.TIME_WAIT:最纠结的状态来了。从状态图上可以看出,有3个状态可以转化成它,我们一一来分析:

    a.由FIN_WAIT_2进入此状态:在双方不同时发起FIN的情况下,主动关闭的一方在完成自身发起的关闭请求后,接收到被动关闭一方的FIN后进入的状态。

    b.由CLOSING状态进入:双方同时发起关闭,都做了发起FIN的请求,同时接收到了FIN并做了ACK的情况下,由CLOSING状态进入。

    c.由FIN_WAIT_1状态进入:同时接受到FIN(对方发起),ACK(本身发起的FIN回应),与b的区别在于本身发起的FIN回应的ACK先于对方的FIN请求到达,而b是FIN先到达。这种情况概率最小。

    关闭的4次连接最难理解的状态是TIME_WAIT,存在TIME_WAIT的2个理由:

    1.可靠地实现TCP全双工连接的终止。

    2.允许老的重复分节在网络中消逝。

     
    展开全文
  • 近日在对学员们讲解TCP状态转移时,看到他们一脸懵逼的表情,甚是心疼。 昨日灵感来了,想起《三体》里地球三体组织和三体时间的通信正适合用来描述TCP状态转移,并且询问了手里的几个学员是否看过《三体》,令人...
  • 这是网络编程的基础,tcp状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析: 1.CLOSED:起始点,在超时或者连接关闭时候进入此状态。2....
  • 上两周无意中讨论起这个话题,发现andy同学对此甚为熟悉,...这是网络编程的基础,tcp状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析:
  • [转]TCP状态转移图学习总结

    千次阅读 2012-12-27 14:44:43
    这是网络编程的基础,tcp状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析: 1.CLOSED:起始点,在超时或者连接关闭时候进入此状态...
  • (转)TCP状态转移图学习总结

    千次阅读 2011-03-03 19:26:00
    这是网络编程的基础,tcp状态转移图说到底就是一个状态机的不同状态之间的转换关系以及触发这些状态需要的条件,一共存在11个状态,我们来逐一分析: <br />1.CLOSED:起始点,在超时或者连接关闭时候...
  • tcp状态转移

    千次阅读 2017-08-13 16:41:05
    TCP状态转移图一个正常连接和断开过程客户端和服务器端的状态转移如下: 其中TIME_WAIT 状态是在服务端发送FIN后,客户回复ACK后,客户端需要等待2MSL时间(报文最大生存时间): 1. 此时若是客户端回复的ACK因为网络...
  • TCP状态转移

    2019-09-10 21:02:44
    TCP状态转移 在前一篇文章已经介绍了TCP协议的三次握手和四次挥手。总的来说,TCP通信过程包括三个步骤:建立TCP连接(三次握手)、数据传输、终止TCP连接(四次挥手)。但是在这个通信过程中,有非常复杂的状态问题...
  • TCP状态转移详解

    2018-06-05 18:00:25
    在看TCP状态转移图之前,我们先来看一下三次握手和四次挥手画了一个比较简陋的图1、建立连接协议(三次握手) (1)客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。 (2) 服务器端回应...
  • 下图为完整的TCP状态转移图,它描绘了所有的TCP状态以及可能的状态转换。 图中的粗虚线表示典型的服务器端连接的状态转移;粗实线表示典型的客户端连接的状态转移。CLOSED是一个假想的起始点,并不是一个实际状态。...
  • TCP/IP 状态转移图

    2020-08-26 22:28:33
    TCP/IP 11状态转移图 详细解释 TCP state transition description table TCP connection state Description LISTEN Waiting for a connection request from a...
  • 读懂TCP状态转移

    2019-02-23 15:15:48
    读懂TCP状态转移过程,对理解网络编程颇有帮助,本文将对TCP状态转移过程进行介绍,但各状态(总共11个)含义不在本文介绍的范围,请参考文末的书目列表。 TCP状态转换(state transition diagram) 1. 建立...
  • TCP 状态转移

    2016-07-17 18:32:37
    TCP协议可靠传输协议,它的可靠性是有它的面向连接的性质所决定,在TCP连接与断开的时候会出现不同的状态,各种状态之间的存在相互转换,因此便有了状态转移机这个概念,下就是TCP连接的11种状态之间的转换 ...
  • TCP连接的任意一端在任一时刻都处于某种状态,当前的状态可以通过...中粗虚线表示典型的服务器端连接的状态转移;粗实线表示典型的客户端连接的状态转移。请注意,CLOSED是一个假想的起始点,并不是一个实际的...
  • TCP状态转移

    2018-05-21 14:35:30
    TCP状态转移3次握手 4次挥手这是典型的TCP流程,3次握手机建立连接,4次挥手断开连接。在这中间就是相应的数据传输。为什么3次握手?假设如果是2次握手,则会出现这种情形。当一个客户端发送的请求在网络中延误,而...
  • TCP连接的状态转移

    2017-05-22 14:56:08
    TCP状态转移
  • TCP状态转换

    2014-04-26 19:50:11
    最全的TCP状态转换

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,881
精华内容 11,152
关键字:

tcp状态转移图