java socket 参数说明

    Socket 的 I/O 调用可能会因为多种原因而阻塞。数据输入方法 read()和 receive()在没有数据可读时会阻塞。TCP 套接字的 write()方法在没有足够的空间缓存传输的数据时可能阻塞。 ServerSocket 的 accept()方法和 Socket 的构造函数都会阻塞等待,直到连接建立(见第6.4 节)。同时,长的信息往返时间,高错误率的连接和慢速的(或已发生故障的)服务器,都可能导致需要很长的时间来建立连接。所有这些情况,只有在连接请求得到满足后这些方法才会返回。

    当然,调用一个已经阻塞的方法将使应用程序停止(并使运行它的线程无效)。当程序在等待一次调用的完成时如果还有其他任务要执行的情况会怎样(如,更新"忙碌"状态的光标或响应用户请求)?这些程序可能没有时间来等待一个阻塞的方法调用。那UDP 数据报文丢失的情况呢?如果我们阻塞等待接收一个数据报文,而它已经丢失,则会导致程序无限期地阻塞下去。


accept(),read()和 receive()
    对于这些方法,我们可以使用 Socket 类、ServerSocket 类和 DatagramSocket 类的setSoTimeout()方法,设置其阻塞的最长时间(以毫秒为单位)。如果在指定时间内这些方
法没有返回,则将抛出一个 InterruptedIOException 异常。对于 Socket 实例,在调用 read()方法前,我们还可以使用该套接字的 InputStream 的 available()方法来检测是否有可读的数据。


写数据

    write()方法调用也会阻塞等待,直到最后一个字节成功写入到了 TCP 实现的本地缓存中。如果可用的缓存空间比要写入的数据小,在 write()方法调用返回前,必须把一些数据成功传输到连接的另一端(详情见第 6.1 节)。因此,write()方法的阻塞总时间最终还是取决于接收端的应用程序。不幸的是 Java 现在还没有提供任何使 write()超时或由其他线程将其打断的方法。所以如果一个可以在 Socket 实例上发送大量数据的协议可能会无限期地阻塞下去。(第 6.2 节介绍了这个特点可能导致的灾难性后果)


控制默认行为
    TCP/IP 协议的开发者用了大量的时间来考虑协议的默认行为,以满足大部分应用程序的需要。(如果你对此表示怀疑,可以参考 RFC1122 和 1123,它们根据多年的经验对 TCP/IP协议的实现的推荐行为进行了详尽的描述。)

Keep-Alive
    如果一段时间内没有数据交换,通信的每个终端可能都会怀疑对方是否还处于活跃状态。TCP 协议提供了一种 keep-alive 的机制,该机制在经过一段不活动时间后,将向另一个
终端发送一个探测消息。如果另一个终端还出于活跃状态,它将回复一个确认消息。如果经过几次尝试后依然没有收到另一终端的确认消息,则终止发送探测信息,关闭套接字,并在
下一次尝试 I/O 操作时抛出一个异常。注意,应用程序只要在探测信息失败时才能察觉到keep-alive 机制的工作。
    默认情况下,keep-alive 机制是关闭的。通过调用 setKeepAlive()方法将其设置为 true 来开启 keep-alive 机制。

发送和接收缓存区的大小
    一旦创建了一个 Socket 或 DatagramSocket 实例,操作系统就必须为其分配缓存区以存放接收的和要发送的数据。Socket, DatagramSocket: 设置和获取发送接收缓存区大小:
int getReceiveBufferSize()
void setReceiveBufferSize(int size)
int getSendBufferSize()
void setSendBufferSize(int size)

    getReceiveBufferSize(),setReceiveBufferSize(),getSendBufferSize(), 和setSendBufferSize()方法分别用于获取和设置接收发送缓冲区的大小(以字节为单位)。需要注意的是,这里指定的大小只是作为一种建议给出的,实际大小可能与之存在差异。

    还可以在 ServerSocket 上指定接收缓冲区大小。不过,这实际上是为 accept()方法所创建的新 Socket 实例设置接收缓冲区大小。为什么可以只设置接收缓冲区大小而不设置发送缓冲区的大小呢?当接收了一个新的 Socket,它就可以立刻开始接收数据,因此需要在accept()方法完成连接之前设置好缓冲区的大小。另一方面,由于可以控制什么时候在新接受的套接字上发送数据,因此在发送之前还有时间设置发送缓冲区的大小。
ServerSocket: 设置/获取所接受套接字的接收缓冲区大小:
int getReceiveBufferSize()
void setReceiveBufferSize(int size)
    getReceiveBufferSize()和 setReceiveBufferSize()方法用于获取和设置由 accept()方法创建的 Socket 实例的接收缓冲区的大小(字节)。

超时
    如前面所介绍的,很多 I/O 操作如果不能立即完成就会阻塞等待:读操作将阻塞等待直到至少有一个字节可读;接收操作将阻塞等待直到成功建立连接。不幸的是阻塞的时间没有
限制。可以为各种操作指定一个最大阻塞时间。
   

地址重用
    对于 TCP,当一个连接关闭后,通信的一端(或两端)必须在"Time-Wait"状态上等待一段时间,以对传输途中丢失的数据包进行清理(见第 6.4.2 节)。不幸的是,通信终端可能无法等到 Time-Wait 结束。对于这两种情况,都需要能够与正在使用的地址进行绑定的能力,这就要求实现地址重用。
Socket, ServerSocket, DatagramSocket: 设置/获取地址重用
    boolean getReuseAddress()
    void setReuseAddress(boolean on)

消除缓冲延迟
    TCP 协议将数据缓存起来直到足够多时一次发送,以避免发送过小的数据包而浪费网络资源。虽然这个功能有利于网络,但应用程序可能对所造成的缓冲延迟不能容忍。好在可
以人为禁用缓存功能。
    Socket: 设置/获取 TCP 缓冲延迟
    boolean getTcpNoDelay()
    void setTcpNoDelay(boolean on)
getTcpNoDelay()和 setTcpNoDelay()方法用于获取和设置是否消除缓冲延迟。将值设置为 true 表示禁用缓冲延迟功能。


紧急数据
    假设你已经向一个慢速接收者发送了很多数据,突然又有了它急需的其它数据。如果将这些数据发送到输出流,它们将追加在常规数据队列的后面,无法保证接收者能够立即接收。为了解决这个问题,TCP 协议中包含了紧急(urgent)数据的概念,这类数据可以(理论上来说)跳到前面去。由于它们能够绕过常规数据流,这些数据称为频道外数据。
Socket: 紧急数据
    void sendUrgentData(int data)
    boolean getOOBInline()
    void setOOBInline(boolean on)

    要发送紧急数据需要调用 sendUrgentData() 方法,它将发送其 int 参数的最低位字节。要接收这个字节,必须为 setOOBInline()方法传递 true 参数启用接收者对频道外数据的接收。该字节在接收者的输入流中被接收。发送于紧急字节之前的数据将处于接收者的输入流中的紧急字节前面。如果没有启用接收者接收频道外数据的功能,紧急字节将被无声地丢弃。
    注意 Java 中的紧急数据几乎没什么用,因为紧急字节与常规字节按照传输的顺序混在了一起。实际上,Java 接收者并不能区分其是否在接收紧急数据。

关闭后停留
    当调用套接字的 close()方法后,即使套接字的缓冲区中还有没有发送的数据,它也将立即返回。这样不发送完所有数据可能导致的问题是主机将在后面的某个时刻发生故障。
其实可以选择让 close()方法"停留"或阻塞一段时间,直到所有数据都已经发送并确认,或发生了超时。详情见第 6.4.2 节
Socket: 在 close()方法停留
    int getSoLinger()
    void setSoLinger(boole
如果调用 setSoLinger()并将其设置为 true,那么后面再调用的 close()方法将阻塞等待,直到远程终端对所有数据都返回了确认信息,或者发生了指定的超时(秒)。如果发生了超
时,TCP 连接将强行关闭。如果开启了停留功能,getSoLinger()方法将返回指定的超时时间,否则返回-1。

int getSoLinger()
void setSoLinger(boolean on, int linger)

猜你喜欢

转载自san-yun.iteye.com/blog/1722223
今日推荐