zoukankan      html  css  js  c++  java
  • Socket基础知识分享

    Socket  Programming Considerations

    写Socket程序的时候需要注意设置下面的timeout,避免对方没有响应的时候,导致Socket程序挂起或等待时间过长

     

    1.1         Accept Timeout

    Accept timeout 仅对ServerSocket有用。ServerSocket 使用accept()方法来监听客户端Socket的连接。默认,ServerSocket.accept() 方法会一直阻塞直到有客户端来连接。通常,我们不需要设置accept timeout.

     

    但有时候特殊情况,还是要考虑设置accept timeout.

    比如: 程序A给程序B发了一个JMS消息,然后程序A启动一个Socket Server,想通过socket等待接收程序B的返回消息。如果不设置accept timeout, 并且程序B因为某些原因一直不能连接Socket Server,最终会导致程序A挂起。

     

    Accept Timeout可以这样设置:

    ServerSocket serverSocket = new ServerSocket(5555);

    serverSocket.setSoTimeout(5000); // in milliseconds

    while (true) {

        Socket socket = serverSocket.accept();

            …

    }

     

    1.2         Connect Timeout

    当Client端连接Server端的时候,可以指定Connect Timeout

    如果没有指定,会使用操作系统的默认值:

    OS

    Default TCP timeout

    BSD

    75 seconds

    Linux

    189 seconds

    Solaris

    225 seconds

    Windows XP

    21 seconds

     

    Connect Timeout可以这样设置:

    SocketAddress socketAddress = new InetSocketAddress(host, port);

    socket = new Socket();

    socket.connect(socketAddress, connectTimeout);

     

    1.3         Receive Timeout

    当socket从另一方接收数据时,可以设置Receive Timeout

    默认没有timeout,socket会一直阻塞直到有数据可读取。

    Receive Timeout可以这样设置:

    Socket socket = new Socket(host, port);

    socket.setSoTimeout(timeout);

     

    1.4         Send Timeout

    Send Timeout是socket给另一方发送数据时使用的。

    不过Java里没有办法设置Send Timeout.

    当然,socket发送数据的时候,会首先发送到本机OS的一个buffer内。一般只要一次发送的数据不是很大,即使对方挂起或暂时不能接收数据,也不会导致发送方挂起。

     

    2.1       Socket ack (acknowledgement)

    Socket ack是指当socket接收到数据之后,发送一个ack字符串(比如$ACK)给socket发送方。这样,socket发送方可以根据是否收到了ack判断对方是否收到了数据。

    Socket ack是显示的在应用程序中加入的一种通讯协议。如果不使用ack,在socket通讯中,可能会丢失数据。

     

    比如,socket client要连续的给socket server发送100条消息。如果我们在server收到第50条消息的时候,强行kill了server。那么查询client端发送的log,可能client端成功发送了51条。只有当client端发送第52条消息的时候才遇到异常。这样第51条消息就丢失了。

    所以为了确保数据传输的准确性,我们可以引入ack协议。有时我们不仅要确保server不但收到了数据,而且还要保证server成功处理了数据。这时,可以等server成功处理完数据之后,再给client发ack。

     

    2.2       Socket Keep Alive

    Socket连接像数据库连接一样,属于重量型资源。如果我们频繁的创建socket、发送/接收数据、关闭socket,那么会有很大一部分时间浪费在socket的创建和关闭上。

    所以,如果我们经常需要与同一个socket地址发送/接收数据时,应该考虑只创建一次socket,然后一直使用这个socket对象发送/接收数据。

     

    2.3       Heartbeat

    通常,我们会设置socket的receive timeout。这样,如果我们一直打开着socket (keep alive), 而很长时间又没有数据通讯,socket接收方就会timeout,最终导致打开的连接坏掉。

    如果很长时间没有数据通讯,防火墙或代理服务器也可能会关闭打开的socket连接。

    所以为了保证打开的socket连接一直可用,如果一段时间没有数据进行通讯(或指定一个时间间隔),我们可以显示的发送一个heartbeat消息(比如: $HRT)给对方,从而保证连接不会被异常关闭。

     

    2.4       Socket Close

    每一个socket对象会持有一个socket descriptor (其实就是file descriptor),操作系统对于socket descriptor有一个最大限制。因此当socket不再使用时,一定要记得关闭,即使socket连接失败或出现异常,只要socket对象不为null,一定要记得关闭。

    下面图显示了,当socket关闭时,socket的状态变化(socket状态可以通过netstat命令查看)。更详细的解释,可以google一下。

     

    当主动一方调用close(先调用close)时的状态变化:

    ESTABLISHED -> FIN_WAIT_1-> FIN_WAIT_2 -> TIME_WAIT -> CLOSED

    当被动一方调用close(后调用close)时的状态变化:

    ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED

    通常,TIME_WAIT 是正常状态,过一段时间(2MSL, 1到4分钟)就会自动消失.

    我们需要特别注意CLOSE_WAIT 状态:

    1.如果很长时间才消失,表明socket server处理太慢,很多client已经连接到server,发送完数据并close了。

    2.如果一直也不消失,表明有socket没有正常close (对方已经close了)

     

    2.5   SO_REUSEADDR Option

    当socket主动调用close的时候,从上面可以知道,它最终会进入TIME_WAIT 状态,需要过1到4分钟,才能完全close。

     

    当socket处于TIME_WAIT 状态时,它仍然占用正在使用的IP/PORT。这样,如果我们的程序(比如socket server)使用了一个固定的IP/PORT,当socket处于TIME_WAIT 状态时,程序将不能立即重启,会出现端口占用错误。

     

    Socket提供了一个setReuseAddress()方法,可以设置当socket处于TIME_WAIT状态时,是否允许其它进程绑定这个端口。

     

    如果我们正在开发socket server,一定要记得调用ServerSocket.setReuseAddress(true).

    Client socket也有这个方法,而且有时可能需要指明client连接server时所使用的本地IP/PORT(一般不用指明,系统会随机选择一个PORT)。但实际测试,在client socket上设置这个方法在Windows和Solaris下并不起作用。当socket处于TIME_WAIT 状态时,重启client仍然出现端口占用错误。上网搜索了很长时间,很多人都碰到了这个问题,可能是操作系统底层socket实现问题。因为测试使用C语言开发的socket client,同样也有这个错误。有人说LINUX下好用,还有就是可以尝试修改tcp_time_wait_interval来减小TIME_WAIT等待时间
  • 相关阅读:
    Longest Palindromic Substring
    PayPal MLSE job description
    Continuous Median
    Remove Duplicates From Linked List
    Valid IP Address
    Longest substring without duplication
    Largest range
    Subarray sort
    Multi String Search
    Suffix Trie Construction
  • 原文地址:https://www.cnblogs.com/kevinGao/p/2236169.html
Copyright © 2011-2022 走看看