使用套接字传输大文件

发布于 2024-10-18 22:25:04 字数 1434 浏览 0 评论 0原文

当我使用套接字编程传输大文件时,收到的文件不完整,即它是一个 mp3 文件,当我播放时听起来很奇怪。 代码是:

服务器端:

File myFile = new File("abc.mp3");
{
    Socket sock = servsock.accept();
    int packetsize=1024;
    double nosofpackets=Math.ceil(((int) myFile.length())/packetsize);
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    for(double i=0;i<nosofpackets+1;i++) {
        byte[] mybytearray = new byte[packetsize];
        bis.read(mybytearray, 0, mybytearray.length);
        System.out.println("Packet:"+(i+1));
        OutputStream os = sock.getOutputStream();
        os.write(mybytearray, 0,mybytearray.length);
        os.flush();
    }
}

客户端:

int packetsize=1024;
FileOutputStream fos = new FileOutputStream("zz.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
double nosofpackets=Math.ceil(((int) (new File("abc.mp3")).length())/packetsize);
for(double i=0;i<nosofpackets+1;i++)
{
    InputStream is = sock.getInputStream();
    byte[] mybytearray = new byte[packetsize];
    int bytesRead = is.read(mybytearray, 0,mybytearray.length );
    System.out.println("Packet:"+(i+1));
    bos.write(mybytearray, 0,mybytearray.length);
}
sock.close();
bos.close();

在客户端,我使用了 new File("abc.mp3")).length只是为了简单起见(我可以从服务器端发送文件的长度)。

如果客户端和服务器在同一台机器上,此代码可以完美运行,但如果它们位于不同的机器上,文件就会失真。

When I'm transferring a large file using socket programming, the received file is incomplete i.e. it is an mp3 file which when i play sounds weird.
The code is:

Server side:

File myFile = new File("abc.mp3");
{
    Socket sock = servsock.accept();
    int packetsize=1024;
    double nosofpackets=Math.ceil(((int) myFile.length())/packetsize);
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
    for(double i=0;i<nosofpackets+1;i++) {
        byte[] mybytearray = new byte[packetsize];
        bis.read(mybytearray, 0, mybytearray.length);
        System.out.println("Packet:"+(i+1));
        OutputStream os = sock.getOutputStream();
        os.write(mybytearray, 0,mybytearray.length);
        os.flush();
    }
}

Client side:

int packetsize=1024;
FileOutputStream fos = new FileOutputStream("zz.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
double nosofpackets=Math.ceil(((int) (new File("abc.mp3")).length())/packetsize);
for(double i=0;i<nosofpackets+1;i++)
{
    InputStream is = sock.getInputStream();
    byte[] mybytearray = new byte[packetsize];
    int bytesRead = is.read(mybytearray, 0,mybytearray.length );
    System.out.println("Packet:"+(i+1));
    bos.write(mybytearray, 0,mybytearray.length);
}
sock.close();
bos.close();

On the Client side I have used new File("abc.mp3")).length just for simplicity (I could send the length of the file from the server side).

This code works perfectly if client and server are the same machine, but the file gets distorted if they are on different machines.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

燕归巢 2024-10-25 22:25:04

在 Java 中复制流的规范方法:

int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

适用于任何大于零的缓冲区大小。应极力避免将缓冲区大小与输入大小相关联。

The canonical way to copy a stream in Java:

int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

Works with any buffer size greater than zero. The temptation to relate the buffer size to the input size should be strenuously avoided.

GRAY°灰色天空 2024-10-25 22:25:04

我认为问题在于您忽略了各种 read 调用返回的值,并假设它们完全填充了缓冲区。这是有问题的:

  • 从文件读取时,最后读取可能不会填充缓冲区。

  • 从套接字读取时,任何读取都可能在填充缓冲区之前返回。

您写入的最终结果会将垃圾放入流(在服务器端)和目标文件(在客户端)中。

此外,根据文件的大小将文件分成块是没有意义的。一直读到文件末尾。

I think that the problem is that you are ignoring the values returned by various read calls, and assuming they completely fill the buffer. This is problematic:

  • When reading from a file, the last read probably won't fill the buffer.

  • When reading from a socket, any read may return before filling the buffer.

The net result that your writes will put junk into the stream (at the server end), and into the destination file (at the client end).

Furthermore, it is pointless dividing the file up into chunks based on the size of the file. Just read until you get to the end of file.

給妳壹絲溫柔 2024-10-25 22:25:04

不要重新发明轮子,请使用 IOUtils。复制()

Don't reinvent the wheel, use IOUtils.copy().

那一片橙海, 2024-10-25 22:25:04

不要使用数据包。
尝试使用 ByteArrayOutputStream 而不是使用静态字节数组。
继续从输入流读取,直到到达 EOF。 n 将其中的每一个写入 ByteArrayOutputStream。


InputStream is = sock.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int byteToBeRead = -1;
while((byteToBeRead = is.read())!=-1){
baos.write(byteToBeRead);
}
byte[] mybytearray = baos.toByteArray();
bos.write(mybytearray, 0,mybytearray.length);

希望这有帮助。

Don't use packets.
Try using the ByteArrayOutputStream instead of using the static byte array.
keep reading from the inputstream until u reach EOF. n write each of this to the ByteArrayOutputStream.


InputStream is = sock.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int byteToBeRead = -1;
while((byteToBeRead = is.read())!=-1){
baos.write(byteToBeRead);
}
byte[] mybytearray = baos.toByteArray();
bos.write(mybytearray, 0,mybytearray.length);

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文