【问题标题】:Java socket output has delayed first messageJava 套接字输出延迟了第一条消息
【发布时间】:2022-02-04 19:27:08
【问题描述】:

Java 中的套接字有一个非常奇怪的问题。这可能是因为我对套接字缺乏了解,但这里是:

我正在使用套接字连接到 IRC 服务器。连接完美,我收到了 IRC 服务器发送给我的所有消息。 建立连接后,我对服务器进行身份验证并启动一个单独的线程来接收服务器发送给我的内容。在那个线程中,我在连接时发送一条消息以使程序加入某个频道。

boolean joined = false;
        while ((line = getInput().readLine()) != null) {
            if (!joined) {
                getOutput().println("JOIN #Random");
                getOutput().println("JOIN #Modnar");

                if (line.contains("JOIN :#Random")) {
                    joined = true;
                    System.out.println("JOINED #Random= true");
                }
            }

在这个方法的最后我调用 getOutput().flush();

现在,当我尝试通过正在编写的客户端向 IRCserver 发送消息时,似乎需要很长时间才能通过第一条消息。当它最终通过时,一切似乎都运行良好。所有后续消息都会立即处理。这只是我在连接并加入该频道后发送的第一条消息,需要很长时间。

我用来向服务器发送消息的方法很简单:

public void sendToServer(String input) {
        getOutput().println(input);
        getOutput().flush();
    }

有没有人知道为什么第一条消息需要这么长时间才能传输到服务器,而以下所有(在第一条最终到达之后)都顺利?

如果值得一提:我正在使用 Tomcat6 作为我建立连接的 servlet,并使用 UnrealIRCd 作为 IRC 服务器。消息通过 AJAX 发送到 servlet。 (但是发送到服务器似乎进展顺利,因为发送消息时我正在执行的 System.out 会立即打印在我的 Tomcat 日志中,因此延迟在套接字或 IRC 服务器中。 )

如果需要更多信息,我会尽量提供,因为这可能看起来很复杂......

【问题讨论】:

  • 如果将 flush() 移到 while 循环中会发生什么?
  • while 循环中实际上有一个刷新。但刷新是在最后,因为我还做了一些 XML 解析(将 XML 发送到客户端)和一个 ping 回复。
  • 使用 Wireshark 监控流量并确定问题是发送延迟,还是服务器响应延迟。
  • 如果找不到解决方案,我打算尝试一下。如果我今晚或明天有时间,我会试一试!

标签: java sockets irc


【解决方案1】:

您的代码似乎在每次绕过 while 循环时都会发送JOIN 命令,这似乎是服务器发送给您的每一行一次,直到您最终从服务器获得确认您已加入的响应频道。

这意味着您最终会发送大量的JOIN 命令。 IRCD 的设计目的是仅处理来自每个客户端的每秒设定的命令速率 - 所以这可能是你落后的原因(你以后的命令最终会排在一个很长的队列的末尾,队列中有很多 JOIN 命令)。

相反,您应该只发送一次JOIN 命令,方法是在发送后立即设置标志:

boolean sent_join = false;
boolean joined = false;

while ((line = getInput().readLine()) != null) {
    if (!sent_join) {
        getOutput().println("JOIN #PrinZ");
        getOutput().println("JOIN #Trinorae");
        sent_join = true;
    }

    if (line.contains("JOIN :#prinz")) {
        System.out.println("JOINED #prinz = true");
        joined = true;
    }
}

请注意,您必须在注册后才能发送您的 JOIN 命令,这由 001 数字表示,因此您可能需要在发送它们之前等待该行。

请注意,line.contains 不是一种非常强大的解析 IRC 消息的方法。如果我向您发送一条包含“JOIN :#prinz”的消息,它也会触发。您应该将每条传入消息分解为源、命令、目标和参数。

【讨论】:

  • 你对那个解析是完全正确的。我正计划改进它,因为它真的很糟糕。有趣的是,最后我已经使用了更体面的解析来生成我的 XML 消息。对于这种导致延迟的糟糕方法,您可能是对的,这使得第一条真正的消息延迟很多!我会尝试改进它并让您知道它是否已修复!提前致谢!
  • 好的!我在 IRCMessage 对象中巧妙地解析了所有内容,将“line.contains("JOIN #PrinZ")”更改为“if(msg.getCommand().equals("001") && !joined)”并设置了joined-当我进入那个 if 时,标记为 true!看来问题是由此连接命令产生的滞后引起的。非常感谢咖啡馆!
  • @Trinorae:没问题。你真的很幸运,它没有立即让你离开服务器 - 如果你连接到一个 MOTD 很长的服务器,它可能会通过消息Excess Flood 断开你的连接。
猜你喜欢
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
相关资源
最近更新 更多