【问题标题】:Java server socket readingJava 服务器套接字读取
【发布时间】:2012-01-03 15:50:00
【问题描述】:

我有一个非常特殊的问题,我最后的办法是在 StackOverflow 上问这个问题,所以请保持开放的心态!

这里有两个程序:

A.客户端:运行在 Android 手机上的 java 客户端。 B. 服务器:在计算机上运行的 java 服务器。

以下是这两个程序的作用:

客户端每 2 毫秒(非常快)发送一次服务器坐标(以字符串格式),服务器必须读取客户端发送给它的所有坐标。为了实现这一点(假设服务器位于 10.0.0.1 并且正在侦听端口 54321),服务器必须有一个套接字,通过该套接字读取所有传入信息。是的,它确实接收到所有信息,但是,有一个问题!

既然你已经了解了故事背后的背景,那么问题来了:

客户端连接到服务器,一旦发生这种情况,它就开始以极快的速度发送坐标(字符串格式)。服务器确实收到了所有消息,但它不会停止读取,除非客户端已断开连接。我需要的是服务器在收到每条消息时单独读取它们!

这是我用来从套接字读取的代码(这是用于服务器的,它在自己的线程上):

    while(true) {
        try {
            BufferedReader socketReader = 
            new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String str = socketReader.readLine();
            System.out.println("New Message: " + str);
            socketReader.close();
        } catch (IOException e) {
            //Client disconnected
            System.out.println("Client disconnected.");
            break;
        }
    }

这是我从客户端得到的输出(其中 x 和 y 是数字):

 New Message: x,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,yx,y...and so on

并且该文本仅在客户端断开连接后显示。我希望它在消息进来时显示出来。

澄清一下,这是所需的输出:

 New Message: x,y
 New Message: x,y
 New Message: x,y
 New Message: x,y
 ... and so on

如果这有任何用处,这里是写入套接字的方法(此代码来自客户端)

PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
while(running) {
    writer = new PrintWriter(socket.getOutputStream(), true);
    writer.write(x+","+y);
    writer.flush();
}

总而言之,我需要让我的服务器在消息进入时读取它们,而不是在客户端断开连接后同时读取它们。 P.S 在 C# 中我还编写了一个服务器,它会读取传入的信息,但在 Java 中这行不通!

【问题讨论】:

  • 是不是有什么问题?似乎发生了 IOException。

标签: java sockets networking tcp


【解决方案1】:

您正在调用readLine,顾名思义,它是用于阅读。您的数据不包含行。

如果可能,请更改您的协议,以便每组坐标都以换行符和/或回车符结束。

不幸的是,我认为你无法让它发挥作用。 2ms 的分辨率在商用网络硬件上是不可能的,如果你试图强迫它,各种各样的东西都会坏掉。如果启用 Nagle,当 ACK 延迟时,您将从 Nagling 获得 200 毫秒的延迟。如果你禁用 Nagle,丢弃一个数据包会让你的延迟飙升。

老实说,我会撕毁设计并重新开始思考您的需求是什么以及您将如何满足这些需求。

您在哪里找到可以每秒发送 500 个数据包的 Android 设备?!我所知道的没有 Wifi 可以做到这一点,GPS 有什么用?

(如果你还没有做一些事情,比如将套接字缓冲区缩小到绝对最小值,使用非阻塞写操作,以及通过中止和删除接收器中的部分数据来处理部分写入,那么你将无法接近满足您的要求。如果连接带宽暂时下降,您不得让数据备份。)

【讨论】:

  • +1 好主意(在我的 flush() 想法之后,但他已经想到了)
  • 哇,哈哈,我要试试如果它有效,我会多次拍自己的背。 :D
  • 好的,大卫你是对的,我在消息中添加了一个“\r\n”。但我也不得不摆脱“socketReader.close;”这一行。好吧,我让它每秒 60 个数据包。任何一天每秒 60 帧都足够了。感谢您所有精彩的输入,非常感谢。顺便说一句,我试图通过执行 socket.noTcpDelay(true); 来禁用 Nagle;那是对的吗?而且我只在客户端的代码上而不是在服务器上这样做我需要在两者上都这样做吗?
  • 服务器是否将任何数据发送回客户端?这会影响 ACK 是否可以搭载以及延迟 ACK 的行为。如果服务器没有发送任何内容,您可能必须禁用 Nagle 并将套接字缓冲区缩小到尽可能小。
  • 问题是,数据备份到套接字缓冲区中。然后服务器将落后于客户端。 (我认为这是不可取的。对吗?)
【解决方案2】:

每次都在客户端的输出套接字上执行flush()。消息实际上正在被缓冲,直到您现在关闭套接字。

【讨论】:

  • 是的,我有 writer.flush();已经在客户的代码上。无论如何感谢您的回复。还有其他建议吗?我也贴一下客户的写法。
猜你喜欢
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多