求教一个 Java 流数据读取的问题

55 天前
dumbbell5kg  dumbbell5kg

问题背景 是对方响应了较长的返回报文,长度是 9.7 万字节,我这边作为接受方调用 SocketInputStream 的 available 方法来判断可读大小是否到达了 9.7 。

测试下来,在其中一台 linux 上 available 方法立即返回了 9.7w 的长度。而另一台 linux 始终只能返回 68176 。

想请教导致这种差异的原因是什么,我该怎么让另一台机器也达到 9.7w 的长度?

1463 次点击
所在节点   程序员  程序员
13 条回复
sujin190
sujin190
55 天前
缓冲区不一样呗,就本来就没说全接收到内存中吧,本来就不可以像你说的这样用
night98
night98
55 天前
这个不是应该读完之后再判断长度够不够吗,你说的这个问题,合理怀疑应该是 linux 网络缓冲区的配置差异问题或者网卡的缓冲区配置问题。理论上最好是读完再判断长度。
zhuangzhuang1988
zhuangzhuang1988
55 天前
流式协议不要预设长度。
dumbbell5kg
dumbbell5kg
55 天前
@night98 报文前几位是长度,我这边拿到长度,再等到 available 返回值达到指定长度再读取数据
night98
night98
55 天前
@dumbbell5kg #4 流不是这么玩的吧,你应该拿到长度之后一直读,直到读到报文指定长度之后就开始你的业务处理就行了。
dumbbell5kg
dumbbell5kg
55 天前
@sujin190 对的,这个问题只要我重复从读取流就行了,但是它是老代码,我现在还没法让他们信任我去改公共代码
dumbbell5kg
dumbbell5kg
55 天前
@night98 哈哈,是的,挺离谱的,老代码,算了,我新业务不用他们的老代码好了。。
sagaxu
sagaxu
55 天前
完全没学过计算机网络?你这思想很危险,你应该一有数据就读,自己维护一个 buffer ,把读到的数据 append 进去,够长度了就整个完整报文丢给业务中的下一层逻辑去处理。如果你一直不读,发送方可能还会阻塞在那边无法继续发送。
sujin190
sujin190
55 天前
@dumbbell5kg 公共库的话这算是比较低级的 bug 了,不让改也是。。
voidmnwzp
voidmnwzp
55 天前
rb := make([]byte, 97000)
n, err := io.ReadFull(reader, rb)
这就是我转 go 的原因。。
wnpllrzodiac
wnpllrzodiac
55 天前
tcp 就没边界,拿多少都有可能。
sagaxu
sagaxu
55 天前
@voidmnwzp

// commons-io
byte[] buffer = new byte[100];
IOUtils.readFully(inputStream, buffer);

// guava
byte[] buffer = new byte[100];
ByteStreams.readFully(inputStream, buffer);

跟 io.ReadFull 有区别?
whp1473
whp1473
55 天前
不能这么玩吧,一般看里面嵌套的协议,比如先读取 32 位固定长度,获得后续报文的内容长度,获得完毕后解析。还有的是判断读取数据的标识符。还有是固定长度的。不能用缓冲大小判断

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1100284

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX