今天有时间重新温习了一下socket,既然温习了总得总结一下吧!
首现Socket有几个选项:
1、TCP_NODELAY:表示立即发送数据。
2、SO_RESUSEADDR:表示允许重用Socket所绑定的本地地址
3、SO_TIMEOUT:表示接受数据时的超时时间。
4、SO_LINGER:表示当执行close();方法时候,是否理解关闭底层的socket。
5、SO_SNFBUF:表示发送数据的缓冲大小
6、SO_RCVBUF:表示接受数据的缓冲区的大小
7、SO_KEEPALIVE:表示长时间处于空闲状态的SOCEKT,是否自动把他/她关闭
8、OOBINLINE:表示是否支持发送一个字节的TCP紧急数据
那我们就详细解释一下以上选项的作用:
1、TCP_NODELAY选项:
setTcpNoDelay(boolean on);
默认情况下发送数据是采用Negale算法。Negale算法是指发送方数据不会立刻发送出去,而是先放在缓冲区内,等待缓冲区满了,在发出去。Negale算法适用于需要发送大量数据的应用场景。这种算法减少传输的次数增加性能。但是如果对于需要即使响应的,小批量数据的应用场景,例如网络游戏就不能采用Negale算法了。默认是false,表示采用Negale算法。
2、SO_RESUSEADDR选项:
setResuseAddress(boolean on);
当接收方通过socket的close()方法关闭socket的时候,如果网络还在发送数据,那么底层的socket不会立即释放本地的端口的,而是等一段时间,确定保证接收到了网络上的延迟数据,然后在释放端口。确保正好不被同样的socket占用这个端口号。
3、SO_TIMEOUT选项:
setSoTimeout(int milins);
用于设置接受数据的等待的超时时间,单位为毫秒,它的默认值是0,表示无限等待。
4、SO_LINGER选项
setSoLinger(boolean on ,int seconds);
默认情况socket的close();方法会立即返回。但是底层的socket并没有立即关闭,他会延迟一段时间,等发送完毕了再关闭。如果执行:
setSoLinger(true,0)的话,会立即关闭,底层的socket也会立即关闭,丢切剩余的数据。如果setSoLinger(true,3600);会在两种情况关闭,第一:数据发送完毕,第二:就是阻塞了3600秒。
5、SO_RCVBUF选项
setReceiveBufferSize(int size);
用于设置输入数据的缓冲区的大小。传输较大的可以使用较大的缓冲区(例如:http,ftp),例如网络游戏实时性较高的,且频繁交互的使用较小的缓冲区。
6、SO_SNDBUF选项
setSendBufferSize(int size);
用于设置输出缓冲区的大小。
7、SO_KEEPALIVE选项
setKeepAlive(boolean on);
当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,超过了2个小时,本地的TCP实现会发送一个数据包给远程的socket,如果远程没有发回响应,TCP会持续尝试11分钟,知道响应为止,如果在12分钟的时候还没响应,TCP尝试关闭socket连接。
8、OOBINLINE选项
setOOBInline(boolean on);
当设置为true的时候,表示支持紧急数据。接收方需要对紧急数据做进一步的处理。使用更高的协议。
对于socket服务类型的选择:
IP规定了4中服务类型:
1、低成本:发送成本低
2、高可靠性:保证鲍数据可靠的发送到目的地
3、高吞吐量:一次接受发送大量数据
4、最小延迟:传输数据快,最快发送到目的地
设置服务类型:setTrafficClass(int trafficClass);
底成本:0x02
高可靠:0x04
最高吞吐量:0x08
最小延迟:0x10
关于socket的设置选项总结完毕!
再来一个实例的封装的方法:
private void setSocketParameters(Socket client_sock) throws SocketException {
if (log.isTraceEnabled())
log.trace("[" + local_addr + "] accepted connection from "
+ client_sock.getInetAddress() + ":"
+ client_sock.getPort());
try {
client_sock.setSendBufferSize(send_buf_size);
} catch (IllegalArgumentException ex) {
if (log.isErrorEnabled())
log.error("exception setting send buffer size to "
+ send_buf_size + " bytes", ex);
}
try {
client_sock.setReceiveBufferSize(recv_buf_size);
} catch (IllegalArgumentException ex) {
if (log.isErrorEnabled())
log.error("exception setting receive buffer size to "
+ send_buf_size + " bytes", ex);
}
// 当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,
//超过了2个小时,本地的TCP实现会发送一个数据包给远程的socket,如果远程没有发回响应,
//TCP会持续尝试11分钟,知道响应为止,如果在12分钟的时候还没响应,TCP尝试关闭socket连接
client_sock.setKeepAlive(true);
//采用negal算法,有数据立即发送出去
client_sock.setTcpNoDelay(tcp_nodelay);
if (linger > 0)
//关闭socket等待liner毫秒后在关闭,
client_sock.setSoLinger(true, linger);
else
//直到把缓存底层数据发送完毕再关闭socekt连接
client_sock.setSoLinger(false, -1);
}