在两台计算机之间传输文件

时间:2014-04-30 11:48:02

标签: java sockets file-transfer

我尝试使用以下代码在两台计算机之间发送文件:

类FileSender:

import java.io.OutputStream;
import java.io.File;

import java.net.Socket;


public class FileSender {
    // host and port of receiver
    private static final int port = 4700;
    private static final String host = "localhost";

    public static void main(String[] args) {
        try {
            Socket socket = new Socket(host, port);
            OutputStream os = socket.getOutputStream();

            int cnt_files = 1;

            // How many files?
            ByteStream.toStream(os, cnt_files);

            for (int cur_file = 0; cur_file < cnt_files; cur_file++) {
                ByteStream.toStream(os, "test.txt");
                ByteStream.toStream(os, new File("test.txt"));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

类FileReceiver:

import java.io.File;
import java.io.InputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class FileReceiver implements Runnable {

    private static final int port = 4700;

    private Socket socket;

    public static void main(String[] _) {
        try {
            ServerSocket listener = new ServerSocket(port);

            while (true) {
                FileReceiver file_rec = new FileReceiver();
                file_rec.socket = listener.accept();

                new Thread(file_rec).start();
            }
        } catch (java.lang.Exception ex) {
            ex.printStackTrace(System.out);
        }
    }

    public void run() {
        try {
            InputStream in = socket.getInputStream();

            int nof_files = ByteStream.toInt(in);

            for (int cur_file = 0; cur_file < nof_files; cur_file++) {
                String file_name = ByteStream.toString(in);
                StringTokenizer st = new StringTokenizer(file_name, "\\");
                ArrayList<String> strings = new ArrayList<String>();
                while (st.hasMoreElements()) {
                    strings.add(st.nextToken().toString());
                }
                System.out.println("c:\\Users\\acer5635\\Documents\\" + strings.get(0));
                File file = new File("c:\\Users\\acer5635\\Documents\\" + strings.get(0));
                ByteStream.toFile(in, file);
            }
        } catch (java.lang.Exception ex) {
            ex.printStackTrace(System.out);
        }
    }
}

类ByteStream:

import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;

public class ByteStream {
    private static byte[] toByteArray(int in_int) {
        byte a[] = new byte[4];
        for (int i = 0; i < 4; i++) {

            int b_int = (in_int >> (i * 8)) & 255;
            byte b = (byte) (b_int);

            a[i] = b;
        }
        return a;
    }

    private static int toInt(byte[] byte_array_4) {
        int ret = 0;
        for (int i = 0; i < 4; i++) {
            int b = (int) byte_array_4[i];
            if (i < 3 && b < 0) {
                b = 256 + b;
            }
            ret += b << (i * 8);
        }
        return ret;
    }

    public static int toInt(InputStream in) throws java.io.IOException {
        byte[] byte_array_4 = new byte[4];

        byte_array_4[0] = (byte) in.read();
        byte_array_4[1] = (byte) in.read();
        byte_array_4[2] = (byte) in.read();
        byte_array_4[3] = (byte) in.read();

        return toInt(byte_array_4);
    }

    public static String toString(InputStream ins) throws java.io.IOException {
        int len = toInt(ins);
        return toString(ins, len);
    }

    private static String toString(InputStream ins, int len) throws java.io.IOException {
        String ret = new String();
        for (int i = 0; i < len; i++) {
            ret += (char) ins.read();
        }
        return ret;
    }

    public static void toStream(OutputStream os, int i) throws java.io.IOException {
        byte[] byte_array_4 = toByteArray(i);
        os.write(byte_array_4);
    }

    public static void toStream(OutputStream os, String s) throws java.io.IOException {
        int len_s = s.length();
        toStream(os, len_s);
        for (int i = 0; i < len_s; i++) {
            os.write((byte) s.charAt(i));
        }
        os.flush();
    }

    private static byte[] toByteArray(InputStream ins, int an_int) throws
            java.io.IOException,
            Exception {

        byte[] ret = new byte[an_int];

        int offset = 0;
        int numRead = 0;
        int outstanding = an_int;

        while ((offset < an_int)
                && ((numRead = ins.read(ret, offset, outstanding)) > 0)) {
            offset += numRead;
            outstanding = an_int - offset;
        }
        if (offset < ret.length) {
            throw new Exception("Could not completely read from stream, numRead=" 
                    + numRead + ", ret.length=" + ret.length); // ???
        }
        return ret;
    }

    private static void toFile(InputStream ins, FileOutputStream fos, int len, int buf_size) throws
            java.io.FileNotFoundException,
            java.io.IOException {

        byte[] buffer = new byte[buf_size];

        int len_read = 0;
        int total_len_read = 0;

        while (total_len_read + buf_size <= len) {
            len_read = ins.read(buffer);
            total_len_read += len_read;
            fos.write(buffer, 0, len_read);
        }

        if (total_len_read < len) {
            toFile(ins, fos, total_len_read, buf_size / 2);
        }
    }

    private static void toFile(InputStream ins, File file, int len) throws
            java.io.FileNotFoundException,
            java.io.IOException {

        FileOutputStream fos = new FileOutputStream(file);

        toFile(ins, fos, len, 1024);
    }

    public static void toFile(InputStream ins, File file) throws
            java.io.FileNotFoundException,
            java.io.IOException {

        int len = toInt(ins);
        toFile(ins, file, len);
    }

    public static void toStream(OutputStream os, File file)
            throws java.io.FileNotFoundException,
            java.io.IOException {

        toStream(os, (int) file.length());

        byte b[] = new byte[1024];
        InputStream is = new FileInputStream(file);
        int numRead = 0;

        while ((numRead = is.read(b)) > 0) {
            os.write(b, 0, numRead);
        }
        os.flush();
    }
}

我首先启动了FileReceiver。 在 FileSende 类中,当我输入host =“localhost”时;该计划工作正常。 但是当我尝试从另一台计算机发送文件时(在我启动 FileSende.java之前,我将执行 FileReceiver.java 的地址设置为host =“192.168.1.2”==&gt; IP) )我遇到了这个例外:

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at ByteStream.toInt(ByteStream.java:35)
    at ByteStream.toString(ByteStream.java:44)
    at FileReceiver.run(FileReceiver.java:41)
    at java.lang.Thread.run(Unknown Source)

两台计算机中的防火墙已关闭(两台计算机的操作系统均为Windows 7 32位。)

1 个答案:

答案 0 :(得分:2)

在终止发送程序之前,您需要确保接收方已完全接收文件。

您可以让收件人在收到文件后发送确认,并在发件人中等待该确认。

在您的情况下,更简单的方法是在发送文件后调用Socket.shutdownOutput()

在您的FileSender中:

for (int cur_file = 0; cur_file < cnt_files; cur_file++) {
    ByteStream.toStream(os, "test.txt");
    ByteStream.toStream(os, new File("test.txt"));
}
socket.shutdownOutput();