|
May
04
|
网游服务器的数据接收机制讨论得比较多, 但发送机制的讨论就少得多了.
写数据和读数据一样, 都会涉及到超时关闭连接的问题. 但是, 读超时一般在应用层实现, 而不是在传输层实现. 一般的网游协议都会设计心跳机制. 写超时不适合在应用层实现, 而应该在传输层实现. 数据的发送(写)操作如果处理不好, 会让服务器进程阻塞写操作上.
写操作的层次
1. 应用层写操作
应用层操作只是将数据拷贝到应用层的发送缓冲, 或者在能明确得知网络调用不会被阻塞的情况下, 直接调用网络接口进行发送. 在两种情况下总是立即返回. 当出现发送缓冲被填满的情况, 这就涉及到阻塞, 这也是本文的重点, 在下面讨论.
2. 传输层写操作
一般指socket的write调用. socket也有其自己的发送缓冲, 在缓冲未满的情况下总是立即返回. 当出现socket的发送已满的情况下, 也会涉及到阻塞.
实现机制:
1. 应用层发送可能出现阻塞的情况
应用层的写方法, 不应该阻塞, 通过出错机制告知发送缓冲已满, 而此时, 写方法的调用者检测到后, 关闭网络连接.
2. 传输层写操作可能出现阻塞的情况
socket的write调用应该在检测到连接可写时才进行写操作, 保证不会出现阻塞. 但应该实现一种超时机制, 当发现某些数据超过一定时间仍无法进行发送时, 关闭网络连接.
结论
客户端的网络和计算能力必须达到一定要求, 如果服务器发送即将出现阻塞, 表明客户端不符合这种要求. 所以, 服务器发送数据接口避免阻塞, 一旦可能出现阻塞(用户层或者传输层缓冲区已满), 就主动关闭连接.
常见的错误观点
一种很常见的错误观点是, 使用了非阻塞的socket接口, 便能避免服务器发送阻塞. 阻塞是一个通用的概念, 而并不仅仅是网络层阻塞. 考虑这样的情况, 服务器源源不断地产生数据, 但网络的速度或者客户端的处理速度太慢, 导致数据越积越多, 最终不可避免, 总有某个地方无法容下这些数据. 这时候, 要么丢包, 要么抵制源(服务器进行)产生数据, 但对于即时网游来说, 应该关闭连接. 因为数据的产生不可避免, 而丢包又不被允许.

Recent Comments