Chinaunix首页 | 论坛 | 博客
  • 博客访问: 80503
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 340
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-02 20:25
文章分类

全部博文(31)

文章存档

2015年(2)

2014年(29)

我的朋友

分类: Java

2014-09-10 18:01:50

1. 3次握手
 
tcp连接建立需要3次握手:
1. C(syn)--->S
2. S(syn+ack)--->C
3. C(ack)--->S。
 仅一次握手肯定是不行的,因为一次握手C无法知道S的状态,若S不可达,C就在那白白的发送数据,浪费资源,不过C在重发了N次会释放连接。
 就两次的话。问题是:C-->S的syn包被网络阻塞了,若这个syn包被S收到时,C跟S已经通信完毕,则S收到syn会认为重新建立连接。但保活定时器可在其超时后回收该无效连接。
 而三次握手不见得就100%可靠了,比如上诉2次握手的问题就被解决了。同样,最后一个ack包被网络阻塞,C重发ack后,C跟S通信完毕。此时S又收到该ack包,此时S处于lisiten状态,对ACK包无视,问题解决。而四次握手就显得多余了,因为ack包是不需要确认的。

2. backlog
 但C跟S3次握手成功后,TCP层会把该连接放入一个接受队列。应用程序通过accept调用,从该队列取出连接。backlog规定了该队列的大小.若队列满,则无法建立新的连接,S将不理会C的syn包,C将开启重传机制,重传syn包。

3. 延迟确认
 
在Tcp中收到一个数据,通常需要回复一个ack包。一个不包含数据的ack报文需要tcp首部,ip首部,链路首部,而实际发送数据可能为零。所以TCP通常会开启一个定时器,将ack跟后续的数据做为一个包传送过去。可以通过TCP_QUICKACK选项快速发送 ACK确认。但Java中貌似没有该选项。

4. Nagle算法
  为了能够减少网络中小分组的数量,避免网络拥塞,可采用nagle算法。该算法规定一个连接上只能有一个未确认的分组,那么在确认收到的时,tcp可以收集很多小分组,并将他们做一个分组发送数据,减少了数据量。它的问题是,确认的到来受到网络的影响,存在时延,所以对待实时性要求高的应用需要关闭该算法。socket.setTcpNoDelay(true)。

5. keepalive
 
正常的连接终止,对方会受到终止连接的包。但异常断开,比如网线被拔出、断电等,对方无法感知,仍会保持一个无效连接。若双方在很长的一段时间无数据交互,则该连接会一直保持。Tcp的解决方案是开启keepalive机制,在双方超过规定时间无数据交互时,发送一个数据包确认对方是否存活。
 通常,判断对方是否存活,可通过应用层自己来实现,比如很久没收到对方数据,可认为断开等。有些应用会自行开发心跳包机制来维持双方的连接状态。

6. 断开连接
 断开一个连接需要四次握手,这是由于TCP是全双工的原因造成的。
1. A->B fin。 
  此时A进入Fin_wait_1,B收到fin后进入Close_wait状态,此时向A发送一个ack,并向应用程序提交一个EOF(也就是read返回-1)。A发送fin后表示不继续发送数据,但仍能接受数据。
2. B->A ack
  A进入fin_wait_2
3. B->A fin
  B进入last_ack状态,A进入time_wait状态。此时双方都不能收发数据
4. A->B ack
  B进入Closed状态。
  java中有对应的半关闭方法。

7. TIME_WAIT
 
一个socket处于TIME_WAIT状态则该socket在2msl时间内不能被重用。这是为了防止之前连接迟到的报文被接收。SO_REUSEADDR选项可使地址在2msl内也可重用。


阅读(818) | 评论(0) | 转发(0) |
0

上一篇:3. NIO--echoserver

下一篇:5.mina概述

给主人留下些什么吧!~~