文章目录
I 设置读取超时时间
1. 设置 Socket 超时时间 , 该超时时间没有实际的概念 , 用于设置与阻塞相关操作的超时时间 , TCP 连接中有两个需要阻塞的操作 :
- ① 连接服务器操作 ;
- ② 等待读取服务器发送给客户端的数据 ;
连接超时时间可以单独设置 , 这里设置的读取超时时间 ;
2. 单位 : 毫秒 ( ms ) ;
3. 设置一个非 0 的超时时间 , 当与 Socket 对象关联的 InputStream 输入流执行 read() 操作时 , 其阻塞时间为这个超时时间 , 如果超过了该时间还没有收到任何数据 , 就会抛出异常 ;
socket.setSoTimeout(3000);
II Socket 复用绑定端口设置
设置是否可以复用 Socket 绑定的地址和端口号 : setReuseAddress( true )
;
socket.setReuseAddress(true);
Socket 连接在建立时 , 会使用之前绑定本地的 IP 地址和端口号 , 这个端口号在使用之后 , 2 分钟之内不允许再次使用 ; 进行了该设置之后 , 可以在连接关闭之后 , 马上使用该本地 IP 地址和端口号 ;
III 开启 Nagle 算法 ( 沾包 )
1. 前提 : TCP 发送数据后 , 接收方会反馈已经接受到的数据 ;
2. 示例 : 客户端如果向服务器端发送 1 字节数据 , 服务器端需要反馈 ACK 信息 , ACK 的命令其大小要比传输的数据还要大 , 其消耗要高于实际的数据传输消耗 ;
3. Nagle 算法引入 : 为了避免上述情况的消耗 , 便有了 Nagle 算法 ;
- ① 服务器端处理 : 其原理是接收端接到数据后 , 如果数据很小 , 那就多接收几个数据 , 然后将反馈信息一起回送给发送端 ;
- ② 客户端处理 : 对应的客户端处理便是一条数据发送之后 , 会等待服务器端反馈 , 然后这段时间内如果又有新的数据要发送 , 那么就会将这些数据缓存起来 , 等待前面的数据反馈信息回送之后 , 将发送端缓存的这些数据全部发送出去 ; 这样就出现了沾包的情况 ;
4. Nagle 算法好处 : Nagle 算法有效的减少了因发送少量数据 , 而产生大量的 ACK 回送包的数据量 ; 优化网络带宽 ;
在需要低延迟传输的情况下是需要关闭该算法的 , 该算法会导致数据沾包情况出现 ;
socket.setTcpNoDelay(true);
IV 心跳包机制
设置了 setKeepAlive(true)
之后的效果 : 如果 TCP 连接在 2 小时之内没有数据传输 , 客户端就会发送心跳包 , 服务器端会会送消息 , 如果客户端没有收到服务器端反馈信息 , 就认为该 TCP 连接已经断开 , 客户端会抛出异常信息 ;
//在长时间 ( 2 小时 ) 没有数据交互 , 是否需要发送心跳包确认连接
socket.setKeepAlive(true);
V 连接关闭处理
1. 连接关闭处理 : 对于连接关闭行为处理方式设置 , 调用 setSoLinger
函数设置 ;
2. 关闭情况说明 : 当 Socket 对象调用 close 方法关闭连接时 , 有可能缓冲区中还有数据没有发送完成 , 这个方法就是用于处理这部分缓冲区数据的 ;
3. setSoLinger
函数原型 :
/**
* Enable/disable {@link SocketOptions#SO_LINGER SO_LINGER} with the
* specified linger time in seconds. The maximum timeout value is platform
* specific.
*
* The setting only affects socket close.
*
* @param on whether or not to linger on.
* @param linger how long to linger for, if on is true.
* @exception SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @exception IllegalArgumentException if the linger value is negative.
* @since 1.1
* @see #getSoLinger()
*/
public void setSoLinger(boolean on, int linger) throws SocketException
4. setSoLinger
参数解析 :
- ① boolean on : TCP 连接关闭处理功能是否打开 , 默认是关闭的 ( false ) ;
- ② int linger : Socket 调用 close 方法后 , 需要阻塞等待缓冲区数据发送的时间 , 单位毫秒 ;
5. 默认状态 : 如果 boolean on
设置成false , 不处理连接的缓存数据 , 调用 close 会立刻关闭连接 , 系统底层会操作输出流发送剩余缓存数据 , 将缓冲区中的数据发送给连接对方 ; 如果设置 false 不会产生阻塞操作 ;
6. 开启连接关闭处理 : setSoLinger( true , 20 ) 情况 , 如果设置 boolean on
参数为 true , int linger
参数设置一个大于等于 0 的参数 , 那么在关闭的时候 , 阻塞 linger 毫秒 , 之后缓冲区如果还有数据 , 就会被丢弃 , 直接向连接对方发送结束命令 , 无需经过超时等待 ;
超时等待是数据达到对方并返回的最长等待时间 ( MSL ) ;
7. 开启连接关闭处理 ( 不阻塞 ) : setSoLinger( true , 0 )
情况 , 如果设置成 0 , 那么其后果是不阻塞 , 也不让系统接管输出流 , 立刻丢弃缓冲区数据 , 向对方发送 RST 命令 ;
VI Socket 紧急数据内敛设置
//设置紧急数据是否内敛 , 默认情况时 false 关闭的 ;
socket.setOOBInline(true);
1. 紧急数据 : 紧急数据是 Socket 对象通过调用 sendUrgentData 发送出去的数据 ; 该方法参数是一个 int 值 , 仅有最低的 8 位是有效的 ;
2. 紧急数据透明特性 : 紧急数据默认情况下与上层的数据是隔离的 , 如客户端给服务器端发送了一条紧急数据 , 服务器端照常接收处理普通数据 , 其不影响数据的接收与处理 , 也不知道客户端发送了紧急数据 ;
3. 接收紧急数据 : 如果服务器端想要接收客户端发送的紧急数据 , 那么需要在获取 Socket 输入流之前设置 socket.setOOBInline(true)
, 才能在接收数据时 , 读取到紧急数据 ;
4. 设置紧急数据 : setOOBInline 方法设置紧急数据是否内敛 , 默认情况时 false 关闭的 ;
5. 适用场景 : 使用紧急数据当做心跳包 ;
不建议设置紧急数据内敛 , 可能会影响实际数据的正确性 ;
VII Socket 设置缓冲区大小
1. 缓冲区大小设置包括两个缓冲区设置 :
- ① 发送缓冲区设置 :
socket.setSendBufferSize(64 * 1024 * 1024);
- ② 接收缓冲区设置 ;
socket.setReceiveBufferSize(64 * 1024 * 1024);
2. 缓冲区作用 : 缓冲区大小默认 32 KB , 缓冲区大小不是要等到有 32 KB 数据才进行发送和接收 , 而是如果发送和接收的数据大于 32 KB , 如 33 KB , 就会将数据拆分成两包 , 32 KB 和 1KB , 然后进行发送和接收操作 ;
注意设置一定要在连接之前设置 , 连接后设置时无效的 ;
VIII Socket 连接性能参数设置
1. 调用 Socket 对象的 setPerformancePreferences
方法 , 设置连接的性能参数 ; 连接有以下三个性能参数 :
- ① 连接时间 ;
- ② 往返延迟 ;
- ③ 带宽 ;
2. 设置的是权重不是具体性能参数 : 设置的值不是具体的参数 , 而是连接的性能权重 , 对哪个性能要求比较高 ;
3. 连接时间 : 如果该 Socket 的连接很频繁 , 连接后传一个数据 , 马上断开 , 这时候比较看重连接时间性能 , 此时可以将第一个参数设置成 10 , 后两个参数设置成 1 , 表示注重连接时间性能 ;
//设置 连接时间 性能参数较重要
socket.setPerformancePreferences(10, 1, 1);
4. 往返延迟 : 如果开发的是网游服务器 , 此时对延迟很看重 , 这时候可以将第二个参数设置成比较高的权重 ;
//设置 往返延迟 性能参数较重要
socket.setPerformancePreferences(1, 10, 1);
5. 带宽 : 如果开发的是音视频服务器 , 注重带宽性能 , 此时需要将第三个参数设置成较高的权重 ;
//设置 带宽 性能参数较重要
socket.setPerformancePreferences(1, 10, 1);
6. 上面的延迟和带宽的性能是互斥的 , 延迟低 , 就意味着很小的包就要发送一次 , 其带宽就低了 , 延迟高了 , 每次积累很多数据才发送 , 其带宽就相应的提高了 ;
7. 函数原型 :
/**
* Sets performance preferences for this socket.
*
* <p> Sockets use the TCP/IP protocol by default. Some implementations
* may offer alternative protocols which have different performance
* characteristics than TCP/IP. This method allows the application to
* express its own preferences as to how these tradeoffs should be made
* when the implementation chooses from the available protocols.
*
* <p> Performance preferences are described by three integers
* whose values indicate the relative importance of short connection time,
* low latency, and high bandwidth. The absolute values of the integers
* are irrelevant; in order to choose a protocol the values are simply
* compared, with larger values indicating stronger preferences. Negative
* values represent a lower priority than positive values. If the
* application prefers short connection time over both low latency and high
* bandwidth, for example, then it could invoke this method with the values
* {@code (1, 0, 0)}. If the application prefers high bandwidth above low
* latency, and low latency above short connection time, then it could
* invoke this method with the values {@code (0, 1, 2)}.
*
* <p> Invoking this method after this socket has been connected
* will have no effect.
*
* @param connectionTime
* An {@code int} expressing the relative importance of a short
* connection time
*
* @param latency
* An {@code int} expressing the relative importance of low
* latency
*
* @param bandwidth
* An {@code int} expressing the relative importance of high
* bandwidth
*
* @since 1.5
*/
public void setPerformancePreferences(int connectionTime,
int latency,
int bandwidth)
来源:https://blog.csdn.net/han1202012/article/details/100528521