【问题标题】:Java reading a file and sending it via DatagramSocketJava读取文件并通过DatagramSocket发送
【发布时间】:2018-10-12 14:58:23
【问题描述】:

使用 Java,我试图通过 DatagramSocket 发送一些文件数据。我需要以 1000 字节的块读取文件并将它们作为数据包发送。我的代码:

  1. 将文件读入字节缓冲区中包装的字节数组中
  2. 将数据放入数据包并发送
  3. 让接收方打开数据包并将内容重新写入新文件。

我在将字节数组写回文件时遇到问题。请在下面查看我的代码。

客户/发件人:

byte[] data = new byte[1000];
ByteBuffer b = ByteBuffer.wrap(data);
DatagramPacket pkt;
File file = new File(sourceFile);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
CRC32 crc = new CRC32();

while(true){
    b.clear();
    b.putLong(0); // I need to put the checksum at the beginning for easy retrieval
    bytesRead = bis.read(data);
    if(bytesRead==-1) { break; }
    crc.reset();
    crc.update(data, 8, data.length-8);
    long chksum = crc.getValue();
    b.rewind();
    b.putLong(chksum);
    pkt = new DatagramPacket(data, 1000, addr); // addr is valid, works fine
    sk.send(pkt);
}

bis.close();
fis.close();

服务器/接收器:

DatagramSocket sk = new DatagramSocket(port);

File destfile = new File("hello.txt");
FileOutputStream fos = new FileOutputStream(destfile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
PrintStream ps = new PrintStream(fos);

byte[] data = new byte[1000];
DatagramPacket pkt = new DatagramPacket(data, data.length);
ByteBuffer b = ByteBuffer.wrap(data);
CRC32 crc = new CRC32();

while(true) {
    pkt.setLength(data.length);
    sk.receive(pkt);
    b.rewind();

    // compare checksum, print error if checksum is different
    // if checksum is the same:
    bos.write(data);  // Where the problem seems to be occurring.

    // send acknowledgement packet. 
}
bos.close();
fos.close();

在这里,我主要是在写回文件时遇到问题。使用一个写着Hello World! 的小文本文件,我得到一个奇怪的输出,写着vˇ]rld!。另外,输入文件只有 12 个字节,但接收方创建的文件是 1KB。

我认为我的问题是处理字节缓冲区 - 我编写了一个使用文件流和缓冲流复制文件的程序,效果很好。但是我对流在这种情况下的工作方式感到困惑,我非常感谢任何帮助。谢谢!

【问题讨论】:

  • 问题:为什么选择 UDP 而不是 TCP?鉴于您是,您确定 1,000 字节的卡盘有意义并且可以独立处理吗?
  • @ControlAltDel 关于协议和块大小的选择,不幸的是,这是一个给定的约束。我必须使用 UDP 并创建最大 1000 字节的数据包。
  • 您的文件为 1KB 是有道理的,因为您发送了一个 1000 字节的数据包。
  • 我没有测试过,但是你可能应该根据ByteBuffer的位置来设置数据包长度。
  • @aglassman 是的,你在两个方面都是对的 - 谢谢!我已经相应地编辑了我的代码,现在效果很好。 :D

标签: java


【解决方案1】:

在发件人的数据[]中,您覆盖了由 crc 从文件中读取的文本!你必须在长后的位置阅读文本。在发件人中更正此问题时,它可以工作:

//int bytesRead = bis.read(data); --old code
int bytesRead=bis.read(data,8,data.length-8);

此外,您发送 1000 个字节,因此将收到 1000 个字节,这些字节将进入 destfile。

顺便说一句:你不检查服务器中的crc....那为什么要发送它?

【讨论】:

  • 谢谢你!我对字节数组如何保存我的输入没有很好的理解。我确实检查了 CRC,我没有将它包含在 sn-p 中,因为它工作正常 :) 如果我可能会问另一个问题,我的程序正在传输(或“复制”)小文件(〜几 KB)很好,但是它在复制稍大的文件(〜MB,很可能是GB)的过程中崩溃了。复制更大的文件时是否必须使用不同的流?
  • 拜托,您能否更具体地了解故障?在服务器端还是客户端?是否出现异常?在您的应用程序协议中,文件传输完成时似乎没有信号,所以也许这值得一看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
相关资源
最近更新 更多