为什么Java从套接字中读取随机数量而不是整个消息?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了为什么Java从套接字中读取随机数量而不是整个消息?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3548字,纯文字阅读大概需要6分钟。
内容图文
![为什么Java从套接字中读取随机数量而不是整个消息?](/upload/InfoBanner/zyjiaocheng/821/c50dc9797ff34eb19fc5bd7b5417026e.jpg)
我正在研究一个项目,并对Java套接字有疑问.源文件可以找到here.
在以纯文本成功传输文件大小后,我需要传输二进制数据. (DVD .Vob文件)
我有一个循环,如
// Read this files size
long fileSize = Integer.parseInt(in.readLine());
// Read the block size they are going to use
int blockSize = Integer.parseInt(in.readLine());
byte[] buffer = new byte[blockSize];
// Bytes "red"
long bytesRead = 0;
int read = 0;
while(bytesRead < fileSize){
System.out.println("received " + bytesRead + " bytes" + " of " + fileSize + " bytes in file " + fileName);
read = socket.getInputStream().read(buffer);
if(read < 0){
// Should never get here since we know how many bytes there are
System.out.println("DANGER WILL ROBINSON");
break;
}
binWriter.write(buffer,0,read);
bytesRead += read;
}
我读取了接近99%的随机字节数.我使用的是基于TCP的Socket,
所以我不应该担心低层传输错误.
收到的号码会发生变化,但总是接近尾声
在文件GLADIATOR / VIDEO_TS / VTS_07_1.VOB中收到7258144字节的7266304字节
该应用程序然后挂起阻止读取.我很困惑.服务器正在发送正确的
文件大小并在Ruby中成功实现但我无法使Java版本工作.
为什么我读取的字节数少于通过TCP套接字发送的字节数?
以上是因为你们许多人在下面指出的错误.
BufferedReader吃了我的socket输入的8Kb.可以找到正确的实现
Here
解决方法:
如果你的in是一个BufferedReader,那么你遇到了缓冲超过需要的常见问题. BufferedReader的默认缓冲区大小为8192个字符,大约是您所期望的和您所获得的之间的差异.所以你缺少的数据是在BufferedReader的内部缓冲区内,转换为字符(我想知道为什么它没有因某种转换错误而中断).
唯一的解决方法是在不使用任何缓冲类读取器的情况下逐字节读取第一行.据我所知,Java不提供具有readLine()功能的无缓冲的InputStreamReader(除了已弃用的DataInputStream.readLine(),如下面的注释所示),因此您必须自己完成.我会通过读取单个字节,将它们放入ByteArrayOutputStream直到遇到EOL,然后使用具有适当编码的String构造函数将结果字节数组转换为String来实现.
请注意,虽然您不能使用BufferedInputReader,但是从一开始就没有什么能阻止您使用BufferedInputStream,这将使逐字节读取更有效.
更新
事实上,我现在正在做这样的事情,只是有点复杂.它是一个应用程序协议,涉及交换一些在XML中很好地表示的数据结构,但它们有时会附加二进制数据.我们通过在根XML中包含两个属性来实现它:fragmentLength和isLastFragment.第一个表示二进制数据的字节数跟随XML部分,isLastFragment是一个布尔属性,表示最后一个片段,因此读取方知道将不再有二进制数据. XML以null结尾,因此我们不必处理readLine().阅读代码如下所示:
InputStream ins = new BufferedInputStream(socket.getInputStream());
while (!finished) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int b;
while ((b = ins.read()) > 0) {
buf.write(b);
}
if (b == -1)
throw new EOFException("EOF while reading from socket");
// b == 0
Document xml = readXML(new ByteArrayInputStream(buf.toByteArray()));
processAnswers(xml);
Element root = xml.getDocumentElement();
if (root.hasAttribute("fragmentLength")) {
int length = DatatypeConverter.parseInt(
root.getAttribute("fragmentLength"));
boolean last = DatatypeConverter.parseBoolean(
root.getAttribute("isLastFragment"));
int read = 0;
while (read < length) {
// split incoming fragment into 4Kb blocks so we don't run
// out of memory if the client sent a really large fragment
int l = Math.min(length - read, 4096);
byte[] fragment = new byte[l];
int pos = 0;
while (pos < l) {
int c = ins.read(fragment, pos, l - pos);
if (c == -1)
throw new EOFException(
"Preliminary EOF while reading fragment");
pos += c;
read += c;
}
// process fragment
}
因此,使用以null结尾的XML非常棒,因为我们可以在不更改传输协议的情况下添加其他属性和元素.在传输级别,我们也不必担心处理UTF-8,因为XML解析器会为我们做.在你的情况下,你可能对这两行很好,但如果你以后需要添加更多的元数据,你也可以考虑使用以null结尾的XML.
内容总结
以上是互联网集市为您收集整理的为什么Java从套接字中读取随机数量而不是整个消息?全部内容,希望文章能够帮你解决为什么Java从套接字中读取随机数量而不是整个消息?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。