`

网络编程-TCP笔记

阅读更多

    很久没写博客了,最近也看了不少书,看完了好像印象不深,还是回头写写记录下吧。。

 

1.TCP机制
    TCP提供了可靠性 ,当TCP向另外一端发送数据时,它要求对端返回一个确认。如果没有收到确认,TCP就自动重传数据并等待更长的时间。在数次重传失败后,TCP才放弃,如此在尝试发送数据上所花的总时间一般为4-8分钟(依赖具体实现)。
    TCP含有用于动态估算客户和服务器之间的往返时间(round-trip time,RTT)的算法 ,以便它知道等待一个确认需要多少时间。
    TCP通过给其中每个字节关联一个序列号对所发送的数据进行排序。 接受端TCP将先根据它们的序列号重新排序,再把结果数据传递给应用。如果收到重复的数据(根据序列号),将丢弃该数据。
    TCP提供流量控制。 TCO总是告知对端在任何时刻它一次能够从对端接受多少字节的数据,这称为通知窗口(advertised window)。在任何时刻,该窗口指出接受缓冲区中当前可用的空间量,从而确保发送端发送的数据不会使接受缓冲区溢出。该窗口时刻动态变化,当接收来自发送端的数据时,窗口大小就减小,但是当接受端应用从缓冲区中读取数据是,窗口大小就增大。通知窗口大小减小到0是有可能的,当TCP对应某个套接字的接受缓冲区已满,导致它必须等待应用从该缓冲区读取时间时,方能从对端再接受数据。

2.TCP连接的建立和终止
    TCP连接的建立的三路握手
 

 
    (1)通常通过调用socket/bind和listen这三个函数来完成,我们称之为被动打开(passive open)。
    (2)客户通过调用connect发动主动打开(active open)。这导致客户TCP发送一个SYN(同步)分节,它告诉服务器客户将在(待建立的)连接中发送的数据的初始化序列号。通常SYN分节不携带数据,其所在IP数据报只含有一个IP首部/一个TCP首部及可能有的TCP选项。
    (3)服务器必须确认(ACK)客户的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据和初始化序列号。服务器在单个分节中发送SYN和对客户SYN的ACK(确认)。
    (4)客户必须确认服务器的SYN。
这种交换至少需要3个分组,因此称之为三路握手。

    TCP连接的终止



 
 
 
    TCP连接的终止每个方向都需要一个FIN和ACK,通常需要4个分节,中间两个分节也有可能合并成一个分节。而原理和建立发的包的原理差不多,看图就能明白。

3.TCP状态转换图
    这些状态都可以使用netstat显示。
 



 


 
 
 

    从上图可以看出,值得注意的是,如果该连接的整个目的仅仅是发送一个单分节的请求和接收一个单分节的应答的请求和接受一个单分节的应答,那么使用TCP有8个分节的开销,如果改用UDP,那么只需交换两组:一个承接请求,一个承接应答,当然这也丧失了TCP的可靠性等特性。
    TIME_WAIT状态
    TCP中有关网络编程中TIME_WAIT状态不容易理解。该端点停留在这个状态的持续时间是最常分节生命期(maximum segment lifetime,MSL)的两倍。TIME_WAIT状态有两个存在的理由:(1)可靠地势险TCP全双工连接的终止。该理由容易理解,主要是为了发送最终的ACK(2)允许老的重复分节在网络中消逝。该理由是说TCP必须防止来自某个连接的老的重复分组在该连接已终止后再先,从而被误解成属于同一连接的某个新的化身。

4.TCP三路握手

TCP中调用connect函数将激发三路握手,其中建立连接出现的错误可能有以下几种:

   (1)若TCP客户没有收到SYN分节的响应,则返回ETIMEOUT错误。
   (2)若对客户的SYN的响应是RST(复位),则表明该服务器主机在我们指定的端口没有进程在等待与之连接(例如服务器进程也许没在运行)。这是一种硬错误,客户一接收到RST就马上返回ECONNREFUSD错误。RST是TCP在发生错误时发送的一种TCP分节。产生RST的条件之:目的地为某个端口的SYN到达,然而该端口上没有正在监听的服务器;TCP想取消一个已有连接;TCP接受到一个根本不存在的连接上的分节。
   (3)若客户发生的SYN在中间的某个路由器上引发了一个“destination unreachable”ICMP错哦无,则认为是一个软错误。客户端保存该消息,并按照第一种情况中所述的时间间隔继续发送SYN。若在某个规定的时间(BSD规定75s)后仍未收到响应,则把保存的消息作为EHOSTUNREACH 或ENETUNRACH错误返回给进程。

5.服务器异常情况
    当服务器端被kill掉,将导致想客户端发送一个FIN,然而如果客户端在正在阻塞在可读或者可写状态时,客户端不作反应,知道下次读或写数据时,才响应该错误。这种情况可用其他方法解决,例如select函数或者设置SO_KEEPALIVE时间。

 

----以下是摘录网上的TCP错误原因---

第1个异常是java.net.BindException:Address already in use: JVM_Bind。该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经被启动,并进行监听。此时用netstat –an命令,可以看到一个Listending状态的端口。只需要找一个没有被占用的端口就能解决这个问题。 

第2个异常是java.net.ConnectException: Connection refused: connect。该异常发生在客户端进行new Socket(ip, port)操作时,该异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听。出现该问题,首先检查客户端的ip和port是否写错了,如果正确则从客户端ping一下服务器看是否能ping通,如果能ping通(服务服务器端把ping禁掉则需要另外的办法),则看在服务器端的监听指定端口的程序是否启动,这个肯定能解决这个问题。 

第3个异常是java.net.SocketException: Socket is closed,该异常在客户端和服务器均可能发生。异常的原因是己方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作。 

第4个异常是java.net.SocketException: (Connection reset或者Connect reset by peer:Socket write error)。该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。 

第5个异常是java.net.SocketException: Broken pipe。该异常在客户端和服务器均有可能发生。在第4个异常的第一种情况中(也就是抛出SocketExcepton:Connect reset by peer:Socket write error后),如果再继续写数据则抛出该异常。前两个异常的解决方法是首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对方关闭连接后自己也要关闭该连接。

  • 大小: 44.7 KB
  • 大小: 44.5 KB
  • 大小: 94.6 KB
  • 大小: 24.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics