【问题标题】:Java Socket Connection is flooding network OR resulting in high pingJava Socket Connection 泛滥网络或导致高 ping
【发布时间】:2012-06-16 21:11:51
【问题描述】:

我的 java 套接字代码有点问题。 我正在编写一个 android 客户端应用程序,它通过直接(!)无线连接将数据发送到我的电脑上的 java 多线程套接字服务器。它工作正常,但我想为移动应用程序改进它,因为它现在非常耗电。当我在我的代码中删除两个特殊行时,我的移动设备(htc one x)的 cpu 使用率完全没问题,但是我的连接似乎有很高的 ping 率或类似的东西......

这是我接收客户端数据的服务器代码 sn-p:

while(true)
  {
    try {
                   ....
            Object obj = in.readObject();
            if(obj != null) {
                Class clazz = obj.getClass();
                String className = clazz.getName();
                if(className.equals("java.lang.String")) {
                    String cmd = (String)obj;
                    if(cmd.equals("dc")) {
                        System.out.println("Client "+id+" disconnected!");
                        Server.connectedClients[id-1] = false;
                        break;
                    }
                    if(cmd.substring(0,1).equals("!")) {
                        robot.keyRelease(PlayerEnum.getKey(cmd,id));
                    }
                    else {
                        robot.keyPress(PlayerEnum.getKey(cmd,id));
                    }

                }
            }

    } catch ....

这里是客户端部分,我在 while 循环中发送我的数据:

private void networking() {
    try {
        if(client != null) {
            ....
                out.writeObject(sendQueue.poll());

            ....
        }
    } catch ....

当我写这个为什么时,我每次执行 while 循环时都会发送数据。当 sendQueue 为空时,将发送一个空的“对象”。这会导致“高”网络流量和“高”cpu 使用率。但是:几乎立即收到所有发送 cmets。

当我将代码更改为以下内容时:

while(true)
...
if(sendQueue.peek() != null) {
    out.writeObject(sendQueue.poll());
}
...

cpu 使用情况完全没问题,但我遇到了一些滞后.. 命令到达的速度不够快.. 正如我所说,如果我正在发送数据(使用空对象),它可以正常工作(除了 cpu 使用情况) ) 每次执行。但我确信这是一种非常粗糙的编码风格,因为我有点淹没网络。有什么提示吗?

我做错了什么??


感谢您的帮助!

此致, maaft

【问题讨论】:

    标签: java android sockets connection wireless


    【解决方案1】:

    您的代码的 CPU 密集型版本正在用 null 值淹没输出流。它们算作要传输的数据。尽管您的服务器明确忽略了它们,但它们也有助于最终强制任何有用的数据通过。

    您使用peek 修改的代码更合理。在writeObject 之后调用flush 是一种很好的形式。否则,写入的对象可能会卡在输出缓冲区中并等待更多项目的到来。缓冲是针对多个对象一起发送的情况的性能优化。不做缓冲的流类不需要刷新。

    更好:

    Object item = sendQueue.poll();
    if (item != null) {
        out.writeObject(item);
        out.flush();  // maybe not needed, depending on the class of your stream 
    }
    

    这稍微快一点;如果您打算立即poll,那么评估peek 毫无意义。

    此外,在将套接字传递给SocketOutputStream 之前,在套接字上调用socket.setTcpNoDelay(true)(假设这是您创建输出流的方式)。这将禁用Nagle algorithm,这可能不一定是节省网络带宽的最佳决定,但它是一种快速检查方法,除了调整 TCP 发送/接收缓冲区之外,您的客户端和服务器是否正常工作。如果您与服务器有直接连接,我根本不用担心禁用 Nagle 算法。

    【讨论】:

    • 感谢您的快速答复!我已经用 flush() 方法试过了,但我的命令仍然很晚才到达。奇怪的是,网络泛滥导致命令几乎立即到达。也许是因为 Socket 需要一点时间来对“新”数据而不是稳定的数据流做出反应?我不能指出它..
    • @user1461100 - 你是如何构造所涉及的输出流的?也就是说,它们是什么类型,你在它们上设置了什么或传递给它们的构造函数?
    • @user1461100 - 我将在剩下的时间里离线,但我添加了关于关闭 Nagle 算法的指导,希望这可能是您的问题。
    • 谢谢你,你是天才!禁用 Nagle 算法完全解决了我的问题! :)
    【解决方案2】:

    您应该使用阻塞队列以便 poll() 阻塞,而不是返回 null。发送空值根本没有意义,这只是浪费每个人的时间、带宽和金钱。

    【讨论】:

      【解决方案3】:

      进一步说明,您可能需要查看适用于 Android 的 ARO 工具,该工具可帮助您优化应用,包括网络使用情况。 http://developer.att.com/developer/legalAgreementPage.jsp?passedItemId=9700312

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-26
        • 2011-08-23
        • 2012-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多