gpt4 book ai didi

java - 卡在套接字上的线程写入 : why ? 以及如何防止它?

转载 作者:行者123 更新时间:2023-12-03 12:02:49 26 4
gpt4 key购买 nike

我正在为我的游戏运行服务器。
我正在使用一个非常简单的系统,基本上,有一个专用线程用于读取每个连接的传入数据。
写入完全独立于读取,并且在不断轮询写入任务队列的线程池中完成。

一切都运行良好,即使是在周末晚上同时有超过 500 名连接的玩家。
这意味着超过 500 个线程,这在大多数情况下似乎不会导致任何重大问题。没有过多的 CPU 或网络带宽负载。

除非在一个主要情况下,具有虚假连接的单个玩家可能会阻塞整个系统。
如果我不尝试中断它或强制关闭相应的套接字,它确实经常发生一个线程在 socketOutputStream.write 上保持阻塞很长时间,可能是几个小时。

汉斯,从那里,两个问题:

问题 1:在这种情况下,套接字上的写操作可能会阻塞?

如果读取操作很明显,只要没有新数据要读取,它就会阻塞,我不太明白为什么写入会阻塞,除非我尝试发送的数据超过我的整个网络连接可以处理的总数据量.
在后面的这个案例中,很明显我必须等待并阻塞一段时间......但事实并非如此。我有 200 Mbps 的带宽限制,在高峰时间我几乎无法达到 1 或 2 Mbps。
交换的数据非常少:玩游戏时没有声音、没有图像、没有视频;只有简单的文本命令。

问题 2:在 Socket 类中,有一个方法 setSOTimeout(参见 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/Socket.html 的文档),它设置读取操作的最大超时时间。
如果套接字在超时内没有读取任何内容,则会启动一个特定的异常,让我有机会检查连接是否仍然处于 Activity 状态并做出响应。我已经在使用这种机制来踢出基于此的不响应玩家。
但是,它仅适用于读取操作 .

写操作有类似的东西吗?我什么也找不到。

一些额外的精度:

  • 服务器在 Linux 机器上运行,Java AdoptOpenJDK 11.0.6
  • 玩家可以通过或不通过 SSL 连接(一个 ServerSocket 和一个 SSLServerSocket 正在监听不同的端口)。他们中的大多数(60%)确实使用 SSL。我正在使用带有 Letsencrypt 证书的默认 SSL 配置。使用 SSL 似乎并不比非 SSL 连接慢。
  • Java 8 好像没有这个问题。自从我从 8 升级到 11 后就有了。

  • 谢谢您的回答。

    最佳答案

    如果您继续发送数据但另一端拒绝读取它,则写入套接字可能会阻塞。

    操作系统为传出数据维护一个缓冲区,以防数据丢失并且必须再次发送。当对方确认接收数据(“确认”)时,数据从缓冲区中清除。如果对方停止确认数据但你继续发送,最终缓冲区会填满,进一步的写入尝试将阻塞,这样数据就不会丢失。

    我知道写入套接字没有超时设置。也许您可以在您的应用程序协议(protocol)中添加一条“您还在那里吗”消息,如果您没有得到回复,则关闭连接。另一种选择是从阻塞套接字 IO 转变为非阻塞,但这是一项重大任务。

    关于java - 卡在套接字上的线程写入 : why ? 以及如何防止它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61089264/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com