Java套接字缺陷:从套接字的InputStream读取字符串

6
我正在使用Socket与ServerSocket通信。服务器向我的Socket发送字符串。每个独立的行都是一条消息,当解析时包含信息。为了读取这些文本行,使用了Scanner。
问题在于数据是“间歇性”到达的。虽然服务器持续且均匀地发送数据,但客户端的Scanner读取的数据似乎暂停,一次读取一堆消息(30-40),然后再次暂停。它无限循环重复这个过程。
如果我增加数据发送速率,则暂停持续时间会减少;如果我减慢数据速度(每秒1个消息),则错误仍然存在,并且暂停时间变得非常长。就好像Socket在等待其缓冲区溢出之前不发送任何数据给Scanner;然后刷新所有内容并等待再次溢出。但是,如果我减小Socket的缓冲区大小,什么也不会改变。
应该注意的是,我以前在此方法中使用了Scanner和Socket - 来自服务器端 - 一切都按预期工作。此外,a)我尝试了这个Java教程中的BufferedReader(bug没有改变),b)将服务器传输列表打印到文件中,并以相同的方式从文件中读取,程序按预期工作(消息接收速率恒定等),因此问题似乎在Socket本身中。
那么:如何修复此行为?我已经没有想法了,真的不知道发生了什么。
代码(按要求):
// In try block
// Makes the connection
Socket connection = new Socket(TARGET_MACHINE, PORT_NUMBER);
Scanner reader = new Scanner(connection.getInputStream());

// In new Thread
// In run()
while(!finished) // Boolean exit strategy
{
    if(reader.hasNextLine())
        Sring message = reader.nextLine();
}

这就是我连接和检索字符串的方式。
此外,我接收到的字符串通常有20-40个字符长。

3
贴一些代码,看看发生了什么。 - Manuel Salvadores
这不是一个错误,而是一个特性。可能您在发送方面有一些缓存需要显式清除。 - Tomasz Nurkiewicz
你的TCP协议栈可能会将多个消息合并成单个数据包以进行网络流量优化。如果消息足够短,则30-40条消息可以放入一个单一的数据包中。如果没有代码和更多关于你的暂停时间有多长的具体信息,那么诊断将会很困难。 - highlycaffeinated
2个回答

2

您是否在使用readLine读取数据?

以下是Java文档的摘录,可能对您有用:

由于此方法继续搜索输入以查找行分隔符,因此如果不存在行分隔符,则可能缓冲整个输入以搜索要跳过的行。

您能否附上客户端和服务器代码以查看问题所在?最好使用非常简单的逐字节阅读器检查来自服务器的流是否具有传输中的暂停,也许问题出在写入数据到服务器套接字的方式上... 没有代码很难猜测 :)


是的,我注意到了那行代码,但之前我一直在使用Scanner来解析Socket消息,并没有发现任何问题。主要问题似乎出在Socket连接上,我想先看看能否解决这个问题。 - CodeBunny

2

在服务器端每次写入流时,您是否会清空缓冲区?它可能会缓冲输出并不将其写入流中,直到达到某个阈值为止。


1
假设您正在使用OutputStream,那么只需使用.flush()方法。OutputStream os = socket.getOutputStream(); os.flush();对于流编写器也有类似的方法。BufferedWriter bw = ...; bw.flush(); - Coeffect

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接