socket的底层创建与关闭

来源:互联网 发布:淘宝网店运营培训 编辑:程序博客网 时间:2024/06/05 12:06

                                                                                         Tcp连接的创建与关闭

         看了网络编程的的东西,并且做了一个QQ的项目。socket编程也算是入门了,但是只是会用还是不行的,必须了解底层的实现,这篇博客就把底层的实现总结一遍。网络传输都是通过底层的TCP协议实现的,这个协议真的是很庞大,想要了解TCP的协议内容可以看一下《TCP/IP:卷一》的TCP部分,写的真是相当的经典,这里就不对TCP协议做过多的说明了,后续肯定会加上的。

       Socket的创建

      客户端

      

      当使用Socket(IP,PORT)创建套接字后,java的底层会建立一个包含关键信息(目的IP、端口、本地IP、端口)的数据结构,刚开始建立时,这个套接字的状态是关闭的,然后由TCP等发起向目的端地址的握手信息:

       1.向目的端发送建立连接的信息。

       2.目的端收到信息后,发送确认信息。

      3. 发起端收到目的端的确认信息后,发送收到信息的确认。

    

      经过这个过程后三次握手就完成,服务器和客户端套接字的状态已经是建立状态。我们可能只知道底层是这样,但是为什么是这样的?要向双方建立连接只要双方都已经确认对方已经同意连接就可以了,所以当客户端第一次收到服务器的确认信息之后,此时客户端就确认了服务器已经同意建立连接,然后修改为建立连接状态,并不是等三次握手之后才变成连接建立,所以第二次握手信息完成后,客户端就可以像服务器发送数据,这比服务器那边的数据读取,要早一段时间。而服务器发送了确认信息之后,不知道客户端是否收到了确认信息,所以要等客户端发送来确认消息之后,才改为建立连接状态。如果服务器没有收到建立连接的信息,那么就会发生超时,放弃连接,然后以递增时间间隔重复发送建立连接的消息。如果服务器拒绝连接,那么连接失败。

      服务器端

  

      服务器端先使用ServerSocket创建一个监听客户端连接的套接字,然后使用accept()阻塞进行等待,当没有指定本地IP地址的时候,此套接字能监听所有接口发来的消息。当监听到有客户端建立连接的报文时,这时就会根据此报文创建另一个套接字数据结构,目的IP和port是这条信息的源地址,本地ip和port是这条信息的目的IP和port。然后有这个新的套接字完成与客户端的握手信息。当三次握手完成之后,这个新创建的socket实例就会从服务器关联的列表中移除,作为accept的返回值。然后serverSocket再进入监听状态。

   收到连接信息,创建套接字数据结构,握手信息完成状态图:

    返回socket实例图:


    socket套接字的关闭

     客户端


      当客户端主动调用close()关闭连接之后,会立即返回,然后由底层的TCP协议完成关闭连接的挥手信息。TCP协议有一个非常优雅的地方,当关闭连接的时候,会把客户端留在sendQ中信息,全部发送完,但是这也由服务器RecvQ的剩余空间决定,这也有一个弊端只是保证要发送的数据发送完,并不能保证对方一定会收到。关闭连接并不是双方同时关闭,服务器端可以等发送完数据之后再进行关闭。此时进入半关闭状态。

     服务器端


     当服务器执行close后,向客户端发送一个关闭连接的信息,客户端收到后进入Time_wait状态,防止服务器收不到客户端发送的信息。在time_wait状态套接字的数据结构并不会消失,防止由于网络连接,服务器还没有收到客户端信息,然后再进建立了一个相同的连接,这样会使服务器收到的数据异常。

     总结:在实际编程中,要注意以下几点

       1.程序在没有无限循环时,顺序执行完代码之后程序退出,这时候便导致套接字意外关闭,这时候是没有完成挥手信息的,若是在发送数据,会抛出connection reset异常

      2.当一端主动关闭之后,若另一半再向其读取数据,使用InputStream 的read方法会返回-1,使用ObjectInputstream的readObject会抛出eofException,这一点在使用对象读取时,可以检测对方连接的关闭。

     3.另一端close之后,还可以向其发送数据,这就是TCP半关闭状态,底层还是能接受的到数据的,但是只是关闭端的套接字不能读取到内容,因为已经主动关闭。

0 0
原创粉丝点击