0

クライアントからサーバーにファイルを送信したいのですが、将来的にはそれをやり直すことができます。

したがって、クライアントはサーバーに接続してファイルをアップロードします。動作しますが、最後にハングします..

これがクライアントの私のコードです。サーバー側は非常に似ています。

private void SenderFile(File file) {


    try {

            FileInputStream fis = new FileInputStream(file);
            OutputStream os = socket.getOutputStream();

            IoUtil.copy(fis, os);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

スタックで見つかった IoUtils :)

public static class IoUtil {

    private final static int bufferSize = 8192;

    public static void copy(InputStream in, OutputStream out)
            throws IOException {
        byte[] buffer = new byte[bufferSize];
        int read;

        while ((read = in.read(buffer, 0, bufferSize)) != -1) {
            out.write(buffer, 0, read);
        }
        out.flush();
    }
}

説明: 私のクライアントはサーバーに接続されたソケットを持っており、私は任意のファイルを彼に送信します。私のサーバーはそれをダウンロードしますが、彼がより多くの情報を聞いているため、最後にハングします。別のファイルを選択すると、サーバーは新しいデータを既存のファイルにダウンロードします。

ファイルをサーバーにアップロードし、サーバーを動作させ、別のファイルを適切にダウンロードするにはどうすればよいですか?

ps。関数の最後に ioutil.copy を追加するとout.close、サーバーは動作しますが、接続が失われます。私は何をすべきかわかりません :{


更新後: クライアント側:

private void SenderFile(File file) {
    try {

        FileInputStream fis = new FileInputStream(file);
        OutputStream os = socket.getOutputStream();

        DataOutputStream wrapper = new DataOutputStream(os);
        wrapper.writeLong(file.length());
        IoUtil.copy(fis, wrapper);

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

サーバー側 (クライアントからのメッセージをリッスンするスレッド):

public void run() {
    String msg;
    File newfile;

    try {
        //Nothing special code here

        while ((msg = reader.readLine()) != null) {


            String[] message = msg.split("\\|");
            if (message[0].equals("file")) {//file|filename|size

                String filename = message[1];
                //int filesize = Integer.parseInt(message[2]);

                newfile = new File("server" + filename);


                InputStream is = socket.getInputStream();
                OutputStream os = new FileOutputStream(newfile);

                DataInputStream wrapper = new DataInputStream(is);

                long fileSize = wrapper.readLong();
                byte[] fileData = new byte[(int) fileSize];
                is.read(fileData, 0, (int) fileSize);
                os.write(fileData, 0, (int) fileSize);


                System.out.println("Downloaded file");
            } else

                //Nothing special here too
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

OK、ファイルをダウンロードできるようになりました。まだ一度、別のファイルがダウンロードされていますが、読み取ることができません。たとえば、2 回目はクライアントから file.png を送信します。サーバーで取得しましたが、このファイルは表示できません。前もって感謝します :)

4

1 に答える 1

2

サーバーがファイルを区別できるようにする必要があります。最も簡単な方法は、受信側が1つのファイルに対して何バイトを期待するかを事前に通知することです。このようにして、いつ読み取りを停止して別の読み取りを待つかを認識します。

このSenderFileメソッドは次のようになります。

private void SenderFile(File file)
{
    try
    {
        FileInputStream fis = new FileInputStream(file);
        OutputStream os = socket.getOutputStream();

        DataOutputStream wrapper = new DataOutputStream(os);
        wrapper.writeLong(file.length());
        IoUtil.copy(fis, wrapper);
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}

そして、これはReceiveFileメソッドがどのように見えるかです:

// the signature of the method is complete speculation, adapt it to your needs
private void ReceiveFile(File file)
{
    FileOutputStream fos = new File(file);
    InputStream is = socket.getInputStream();
    DataInputStream wrapper = new DataInputStream(is);

    // will not work for very big files, adapt to your needs too
    long fileSize = wrapper.readLong();
    byte[] fileData = new byte[fileSize];
    is.read(fileData, 0, fileSize);
    fos.write(fileData, 0, fileSize);
}

その後、ソケットを閉じないでください。

于 2012-09-08T14:24:44.847 に答える