Socket有以下几个选项:
n TCP_NODELAY:表示立即发送数据。
n SO_RESUSEADDR:表示是否允许重用Socket所绑定的本地地址。
n SO_TIMEOUT:表示接收数据时的等待超时时间。
n SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket。
n SO_SNFBUF:表示发送数据的缓冲区的大小。
n SO_RCVBUF:表示接收数据的缓冲区的大小。
n SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。
n OOBINLINE:表示是否支持发送一个字节的TCP紧急数据。
1. TCP_NODELAY选项
1) 设置该选项:public void setTcpNoDelay(boolean on) throws SocketException
2) 读取该选项:public boolean getTcpNoDelay() throws SocketException
3) TCP_NODEALY的默认值为false,表示采用Negale算法。如果调用setTcpNoDelay(true)方法,就会关闭Socket的缓冲,确保数据及时发送:
if(!socket.getTcpNoDelay()) socket.setTcpNoDelay(true);
4) 如果Socket的底层实现不支持TCP_NODELAY选项,那么getTcpNoDelay()和setTcpNoDelay()方法会抛出SocketException。
2. SO_RESUSEADDR选项
1) 设置该选项:public void setResuseAddress(boolean on) throws SocketException
2) 读取该选项:public boolean getResuseAddress() throws SocketException
3) 为了确保一个进程关闭了Socket后,即使它还没释放端口,同一个主机上的其他进程还可以立刻重用该端口,可以调用Socket的setResuseAddress(true)方法:
if(!socket.getResuseAddress()) socket.setResuseAddress(true);
4) 值得注意的是socket.setResuseAddress(true)方法必须在Socket还没有绑定到一个本地端口之前调用,否则执行socket.setResuseAddress(true)方法无效。因此必须按照以下方式创建Socket对象,然后再连接远程服务器:
Socket socket = new Socket(); //此时Socket对象未绑定到本地端口,并且未连接远程服务器 socket.setResuseAddress(true); SocketAddress remoteAddr = new InetSocketAddress("remotehost",8000); socket.connect(remoteAddr); //连接远程服务器,并且绑定匿名的本地端口 或者: Socket socket = new Socket(); //此时Socket对象未绑定到本地端口,并且未连接远程服务器 socket.setResuseAddress(true); SocketAddress localAddr = new InetSocketAddress("localhost",9000); SocketAddress remoteAddr = new InetSocketAddress("remotehost",8000); socket.bind(localAddr); //与本地端口绑定 socket.connect(remoteAddr); //连接远程服务器,并且绑定匿名的本地端口 |
3. SO_TIMEOUT选项
1) 设置该选项:public void setSoTimeout(int milliseconds) throws SocketException
2) 读取该选项:public int getSoTimeOut() throws SocketException
3) 当通过Socket的输入流读数据时,如果还没有数据,就会等待。Socket类的SO_TIMEOUT选项用于设定接收数据的等待超时时间,单位为毫秒,它的默认值为0,表示会无限等待,永远不会超时。
4) Socket的setSoTimeout()方法必须在接收数据之前执行才有效。此外,当输入流的read()方法抛出SocketTimeoutException后,Socket仍然是连接的,可以尝试再次读取数据。
4. SO_LINGER选项
1) 设置该选项:public void setSoLinger(boolean on, int seconds) throws SocketException
2) 读取该选项:public int getSoLinger() throws SocketException
3) SO_LINGER选项用来控制Socket关闭时的行为。
l socket.setSoLinger(true,0):执行Socket的close()方法时,该方法也会立即返回,但底层的Socket也会立即关闭,所有未发送完的剩余数据被丢弃。
l socket.setSoLinger(true,3600):执行Socket的close()方法时,该方法不会立即返回,而进入阻塞状态,同时,底层的Socket会尝试发送剩余的数据。只有满足以下两个条件之一,close()方法才返回:
n 底层的Socket已经发送完所有的剩余数据。
n 尽管底层的Socket还没有发送完所有的剩余数据,但已经阻塞了3600秒。close()方法的阻塞时间超过3600秒,也会返回,剩余未发送的数据被丢弃。
以上两种情况内,当close()方法返回后,底层的Socket会被关闭,断开连接。
4) setSoLinger(boolean on ,int second)方法中的seconds参数以秒为单位,而不是以毫秒为单位。
5. SO_RCVBUF选项
1) 设置该选项:public void setReceiveBufferSize(int size) throws SocketException
2) 读取该选项:public int getReceiveBufferSize() throws SocketException
3) SO_RCVBUF表示Socket的用于输入数据的缓冲区的大小。
4) 如果底层Socket不支持SO_RCVBUF选项,那么setReceiveBufferSize()方法会抛出SocketException。
6. SO_SNDBUF选项
1) 设置该选项:public void setSendBufferSize(int size) throws SocketException
2) 读取该选项:public int getSendBufferSize() throws SocketException
3) SO_SNDBUF表示Socket的用于输出数据的缓冲区的大小。
4) 如果底层Socket不支持SO_SNDBUF选项,setSendBufferSize()方法会抛出SocketException。
7. SO_KEEPALIVE选项
1) 设置该选项:public void setKeepAlive(boolean on) throws SocketException
2) 读取该选项:public int getKeepAlive() throws SocketException
3) 当SO_KEEPALIVE选项为true,表示底层的TCP实现会监视该连接是否有效。
4) SO_KEEPALIVE选项的默认值为false,表示TCP不会监视连接是否有效,不活动的客户端可能会永久存在下去,而不会注意到服务器已经崩溃。
8. OOBINLINE选项
1) 设置该选项:public void setOOBInline(int size) throws SocketException
2) 读取该选项:public int getOOBInline () throws SocketException
3) 当OOBINLINE为true时,表示支持发送一个字节的TCP紧急数据。Socket类的sendUrgentDate(int data)方法用于发送一个字节的TCP紧急数据。
4) OOBINLINE的默认值为false,在这种情况下,当接收方收到紧急数据时不作任何处理,直接将其丢弃。如果用户希望发送紧急数据,应该把OOBINLINE设为true:socket.setOOBInline(true); 此时接收方会把接收到的紧急数据与普通数据放在同样的队列中。值得注意的是,除非使用一些更高层次的协议,否则接收方处理紧急数据的能力非常有限,当紧急数据到来时,接收方不会得到任何通知,因此接收方很难区分普通数据与紧急数据,只好按照同样的方式处理它们。
9. 服务类型选项
1) IP规定了四种服务类型,用来定性的描述服务的质量:
l 低成本:发送成本低。
l 高可靠性:保证把数据可靠的送达目的地。
l 最高吞吐量:一次可以接收或发送大批量的数据。
l 最小延迟:传输数据的速度快,把数据快速送达目的地。
2) 这四种服务类型还可以进行组合,例如,可以同时要求获得高可靠性和最小延迟。Socket类中提供了设置和读取服务类型的方法:
l 设置服务类型:public void setTrafficClass(int trafficClass) throws SocketException
l 读取服务类型:public int getTrafficClass() throws SocketException
3) Socket类用四个整数表示服务类型:
l 低成本:0x02 (二进制的倒数第二位为1)
l 高可靠性:0x04(二进制的倒数第三位为1)
l 最高吞吐量:0x08(二进制的倒数第四位为1)
l 最小延迟:0x10(二进制的倒数第五位为1)
10. 设定连接时间、延迟和带宽的相对重要性
public void setPerformancePreferences(int connectionTime,int latency,int bandwidth)
以上方法的三个参数表示网络传输数据的三项指标:
n 参数connectionTime:表示用最少时间建立连接。
n 参数latency:表示最小延迟。
n 参数bandwidth:表示最高带宽。
setPerformancePreferences()方法用来设定这三项指标之间的相对重要性。可以为这些参数赋予任意的整数,这些整数之间的相对大小就决定了相应参数的相对重要性。例如,如果参数connectionTime为2,参数latency为1,而参数bandwidth为3,就表示最高带宽最重要,其次是最少连接时间,最后是最小延迟。