使用 Java 套接字发送文件,丢失数据 [英] Sending a file with Java Sockets, losing data

查看:54
本文介绍了使用 Java 套接字发送文件,丢失数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Java 套接字将文件从客户端发送到服务器.当我在同一台机器上测试时它工作正常,但是当我在不同的机器上测试时,我丢失了大量数据,导致文件损坏.如果我尝试发送一个非常小的文件(<20 字节),它甚至不会到达服务器的 while 循环内的 println.

I'm trying to send a file from a client to a server with Sockets in Java. It works fine when I am testing on the same machine, but when I test across different machines, I lose large chunks of data, resulting in a corrupted file. If I try to send a very small file (<20 bytes), it doesn't even reach the println inside the server's while loop.

这是我的代码:

Server.java

package edu.mst.cs.sensorreceiver;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    private static final int PORT = 51111;
    private static final int CHUNK_SIZE = 1024;
    private static final File _downloadDir = new File("downloads/");

    public static void main(String[] args) {
        if (!_downloadDir.exists()) {
            if (!_downloadDir.mkdirs()) {
                System.err.println("Error: Could not create download directory");
            }
        }

        Socket socket = null;
        try {
            ServerSocket server = new ServerSocket(PORT);

            while (true) {
                System.out.println("Waiting for connection...");
                socket = server.accept();

                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                String name = in.readLine();
                File file = new File(_downloadDir, name);

                String size = in.readLine();
                int fileSize;
                try {
                    fileSize = Integer.parseInt(size);
                } catch (NumberFormatException e) {
                    System.err.println("Error: Malformed file size:" + size);
                    e.printStackTrace();
                    return;
                }

                System.out.println("Saving " + file + " from user... (" + fileSize + " bytes)");
                saveFile(file, socket.getInputStream());
                System.out.println("Finished downloading " + file + " from user.");
                if (file.length() != fileSize) {
                    System.err.println("Error: file incomplete");
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void saveFile(File file, InputStream inStream) {
        FileOutputStream fileOut = null;
        try {
            fileOut = new FileOutputStream(file);

            byte[] buffer = new byte[CHUNK_SIZE];
            int bytesRead;
            int pos = 0;
            while ((bytesRead = inStream.read(buffer, 0, CHUNK_SIZE)) >= 0) {
                pos += bytesRead;
                System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
                fileOut.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOut != null) {
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("Finished, filesize = " + file.length());
    }
}

Client.java

package edu.mst.cs.sensorreceiver;

import java.io.*;
import java.net.Socket;

public class Client {
    private static final String HOSTNAME = "131.151.163.153";
    private static final int PORT = 51111;
    private static final int CHUNK_SIZE = 1024;

    public static void main(String[] args) {
        sendFile(args[0]);
    }

    private static void sendFile(String path) {
        if (path == null) {
            throw new NullPointerException("Path is null");
        }

        File file = new File(path);
        Socket socket = null;
        try {
            System.out.println("Connecting to server...");
            socket = new Socket(HOSTNAME, PORT);
            System.out.println("Connected to server at " + socket.getInetAddress());

            PrintStream out = new PrintStream(socket.getOutputStream(), true);

            out.println(file.getName());
            out.println(file.length());

            System.out.println("Sending " + file.getName() + " (" + file.length() + " bytes) to server...");
            writeFile(file, socket.getOutputStream());
            System.out.println("Finished sending " + file.getName() + " to server");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void writeFile(File file, OutputStream outStream) {
        FileInputStream reader = null;
        try {
            reader = new FileInputStream(file);
            byte[] buffer = new byte[CHUNK_SIZE];
            int pos = 0;
            int bytesRead;
            while ((bytesRead = reader.read(buffer, 0, CHUNK_SIZE)) >= 0) {
                outStream.write(buffer, 0, bytesRead);
                outStream.flush();
                pos += bytesRead;
                System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
            }
        } catch (IndexOutOfBoundsException e) {
            System.err.println("Error while reading file");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Error while writing " + file.toString() + " to output stream");
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

我已经为此工作了几个小时,但几乎没有取得任何进展.我以为我对从流中读取/写入的工作方式有很好的理解,但显然我在这里遗漏了一些东西.

I've been working on this for hours and I have made almost no progress. I thought I had a pretty good understanding of how reading/writing from streams works, but clearly I'm missing something here.

同样,当我从同一台机器发送和接收时,一切正常.但是如果我尝试在两台计算机之间发送文件,即使两者在同一个局域网中,我也会丢失很多发送的数据.

Again, everything works perfectly when I am sending and receiving from the same machine. But if I try to send a file between two computers, even if the two are on the same LAN, I lose a lot of the data that was sent.

有人能解决我的问题吗?我已经尝试了所有我能想到的.

Can anybody figure out my problem? I've already tried everything I could think of.

推荐答案

您似乎在混合分块数据和面向行的操作.我建议你使用 DataInputStream 在服务器上,以及 数据输出流.从客户端开始,类似

You appear to be mixing chunked data and line oriented operation. I suggest you use a DataInputStream on the server, and a DataOutputStream. Starting on the client, something like

private static void sendFile(String path) {
    if (path == null) {
        throw new NullPointerException("Path is null");
    }

    File file = new File(path);
    Socket socket = null;
    try {
        System.out.println("Connecting to server...");
        socket = new Socket(HOSTNAME, PORT);
        System.out.println("Connected to server at "
                + socket.getInetAddress());

        try (DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(socket.getOutputStream()));) {
            dos.writeUTF(file.getName());
            dos.writeLong(file.length());

            System.out.println("Sending " + file.getName() + " ("
                    + file.length() + " bytes) to server...");
            writeFile(file, dos);
            System.out.println("Finished sending " + file.getName()
                    + " to server");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

然后在服务器上

socket = server.accept();

DataInputStream dis = new DataInputStream(socket.getInputStream());
String name = dis.readUTF();
File file = new File(_downloadDir, name);
long fileSize = dis.readLong();
System.out.println("Saving " + file + " from user... ("
        + fileSize + " bytes)");

这篇关于使用 Java 套接字发送文件,丢失数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆