首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么TCP客户端无法使用write检测服务器关闭?

为什么TCP客户端无法使用write检测服务器关闭?
EN

Stack Overflow用户
提问于 2017-06-29 13:10:19
回答 2查看 205关注 0票数 0

我正在构建一个即时通信应用,在客户端,我的代码是这样写的(我在阻塞模式下使用SocketChannel,历史原因,我认为它与这个问题无关):

代码语言:javascript
复制
try {
    LogUtil.info(TAG, this.label + " tryConnect, attempt = " + (3 - retry));
    clientChannel = SocketChannel.open();
    clientChannel.configureBlocking(true);
    clientChannel.socket().setSoTimeout(100);
    clientChannel.socket().setTrafficClass(0x10);
    clientChannel.socket().setTcpNoDelay(true);
    clientChannel.socket().setPerformancePreferences(3, 3, 1);
    clientChannel.socket().connect(address, 10000);
    LogUtil.info(TAG, this.label + " socket connected successfully");
    break;
} catch (AlreadyConnectedException ace) {
    LogUtil.info(TAG, label + " AlreadyConnectedException");
    break;
} catch (NotYetConnectedException ace) {
    LogUtil.info(TAG, label + " NotYetConnectedException");
    break;
} catch (SocketTimeoutException e) {
    LogUtil.info(TAG, label + " SocketTimeoutException");
    break;
} catch (Exception e) {
    clientChannel = null;
    throw new SocketConnectionException(label + ", exception = " + ThrowableUtil.stackTraceToString(e));
}

问题是,当我有时关闭服务器时,客户端将继续成功写入(小块数据,总共不到50字节)。大约3分钟后,客户端遇到写入失败异常。

为什么在服务器关闭后客户端没有立即出现故障?如何解决此问题?也许可以将发送缓冲区减少到10个字节?

编辑

下面是我实际写数据的方式:

代码语言:javascript
复制
public void writeXML(ByteBuffer buffer, int retry) {
        synchronized (writeLock) {
            if (retry < 0) {
                throw new SocketConnectionException(label + "Write Exception");
            }
            tryConnect(false);
            try {
                int written = 0;
                while (buffer.hasRemaining()) {
                    // I think it should be an exception here after I closed server
                    written += clientChannel.write(buffer);
                }
                if (LogUtil.debug) {
                    LogUtil.info(TAG, "\t successfully written = " + written);
                }
            } catch (Exception e) {
                e.printStackTrace();
                tryConnect(true);
                writeXML(buffer, --retry);
            }
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2017-06-29 13:48:32

因为在您和对等应用程序之间有:

套接字发送缓冲区TCP implementation

  • another TCP implementation

  • a
  • 套接字接收缓冲区。

通常情况下,当你写的时候,数据只是被传输到你的套接字发送缓冲区中,并在网络上异步发送。因此,如果发送它时出现错误,您不会立即发现。只有当TCP发送失败的次数超过TCP的内部发送超时时间,您才能确定是否存在错误条件。之后的下一次写(或读)将得到错误。可能需要几分钟的时间。

票数 0
EN

Stack Overflow用户

发布于 2017-06-29 17:51:52

事实证明,read操作可以立即检测到关闭的连接(通过@EJP的回复,这与丢失的连接不同)。

在我的阅读线程中,我有这样一句话:

代码语言:javascript
复制
int read = clientChannel.read(buffer);

,当它返回-1表示服务器已关机(故意关机与网络不可达不同)时,我猜write操作需要填充TCP send buffer,因此没有办法快速检测连接丢失。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44816787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档