2

zipファイルをダウンロードして終了するだけの非常に必要最低限​​のファイルサーバーを作成しようとしていますが、問題が発生しています。私には2つの主な問題があります。

1つ目は、ローカルホストでテストすると、zipファイルを転送するという点で機能しますが、開こうとすると、破損しているというエラーが表示されます。それはzipファイル形式または私がそれを転送する方法と関係があるかもしれません。

2番目の問題は、ローカルホスト以外を使用すると失敗することです。Webサイトを自分のIPにリダイレクトしようとしましたが、IPアドレスを入力するだけで、すべてのファイアウォールとウイルス対策をオフにしても、両方とも失敗します。

サーバーコード:

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

public class FileServer {
    public static void main(String[] args) throws IOException {
    final int PORT_NUMBER = 44444;
    ServerSocket serverSock = null;
    PrintWriter out = null;
    BufferedInputStream bin = null;
    OutputStream os = null;
    Socket clientSock = null;
    File file;
    byte[] fileData;
    String filename = "file.zip";

    while(true) {
        try {
        //Listen on port
        serverSock = new ServerSocket(PORT_NUMBER);

        //Get connection
        clientSock = serverSock.accept();
        System.out.println("Connected client");

        //Get output stream
        out = new PrintWriter(clientSock.getOutputStream(), true);

        out.println(filename);    //Print filename
        file = new File(filename); //Get file
        fileData = new byte[(int)file.length()]; //Stores the file data
        bin = new BufferedInputStream(new FileInputStream(file));
        out.println((int)file.length()); //Print filesize
        bin.read(fileData); //Read contents of file
        os = clientSock.getOutputStream();
        os.write(fileData); //Write the file data
        os.flush();
        } catch(SocketException e) {
        System.out.println("Client disconnected");
        } catch(Exception e) {
        System.out.println(e.getMessage());
        System.exit(1);
        } finally {
        //Close all connections
        System.out.println("Shutting down");

        if(os != null) {
            os.close();
        }

        if(bin != null) {
            bin.close();
        }

        if(out != null) {
            out.close();
        }

        if(clientSock != null) {
            clientSock.close();
        }

        if(serverSock != null) {
            serverSock.close();
        }
        }
    }
    }
}

クライアントコードスニペット。スニペットを切り取ったときに中かっこなどが一致しなかった可能性があるため、すべての構文が正しく、他のすべてが存在して機能していると想定します。

import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;

public static void main(String[] args) {
        final int PORT_NUMBER = 44444;
        final String HOSTNAME = "127.0.0.1";
        String filename = "default.txt";
        Socket sock = null;
        BufferedReader in = null;
        BufferedOutputStream bos = null;
        InputStream is = null;
        byte[] fileData;

        //Attempt to connect
        try {
        sock = new Socket(HOSTNAME, PORT_NUMBER);
        in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        is = sock.getInputStream();
        } catch(UnknownHostException e) {
        JOptionPane.showMessageDialog(this, "Error: could not connect to host " + HOSTNAME + " on port number " + PORT_NUMBER);
        System.exit(1);
        } catch(ConnectException e) {
        JOptionPane.showMessageDialog(this, "Error: connection refused");
        System.exit(1);
        } catch(Exception e) {
        JOptionPane.showMessageDialog(this, e);
        System.exit(1);
        }

        try {
        filename = in.readLine();
        bos = new BufferedOutputStream(new FileOutputStream(filename));
        fileData = new byte[Integer.decode(in.readLine())]; //Gets file size
        is.read(fileData);
        bos.write(fileData);
        bos.flush();
        bos.close();

        if(is != null) {
            is.close();
        }

        if(in != null) {
            in.close();
        }

        if(bos != null) {
            bos.close();
        }

        if(sock != null) {
            sock.close();
        }
        } catch(Exception e) {
        JOptionPane.showMessageDialog(this, e);
        System.exit(1);
        }

        JOptionPane.showMessageDialog(this, "Download complete");
    }
    }
    }                                        

}

編集:.docおよび.docxファイルを使用するローカルホストで問題なく動作します。問題を引き起こすのは.zipのみです。

4

3 に答える 3

2

あなたのクライアントには、問題を引き起こす可能性のある 2 つの問題があります。

a を使用しBufferedReaderて最初の行を読み取り、次にソケットからプレーンな基になる InputStream にアクセスしていますis.read(fileData);

まず、BufferedReader (およびそれは InputStreamReader) は、最初の行だけでなく複数を読み取る場合がありreadLine()ます。残りは後で取得するためにバッファリングされますが、それ以上は読み取れません。そのため、ファイルの先頭が欠落している可能性があります。

read第 2 に、このメソッド呼び出しの結果をチェックしないため、socket-InputStream のメインは 1 つしかありません。したがって、ファイルの末尾は、実際のデータではなくゼロバイトで構成されている可能性があります (最初の問題で見逃したのと同じくらい多くのゼロバイトが存在することは確かです)。代わりに、読み取り呼び出しの結果を確認 (および追加) して、ループ内で読み取る (そしておそらくすぐにファイルに書き込む) 必要があります。

編集:配列への読み取り専用:

int read = 0;
while(read < size) {
    int r = is.read(fileData, read, size-read);
    if(r < 0) {
       // end of file, should not occur if noone interrupts your stream or such
       throw new EOFException("input ended prematurely");
    }
    read += r;
}

これを行うreadFully()方法がDataInputStreamあると思います。より大きなファイルがある場合は、1 つの配列に完全に格納するのではなく、読み書きを交互に行います (より小さい配列をバッファーとして使用します)。

InputStream is = ...;
int len = ...;
OutputStream out = ...;

int read = 0;
byte[] buf = new byte[8000];
while(read < len) {
    int r = is.read(buf);
    if(r < 0) {
       // end of file, should not occur if noone interrupts your stream or such
       throw new EOFException("input ended prematurely");
    }
    out.write(buf, 0, r);
    read += r;
}

doc で動作する理由は推測することしかできません。実際に出力ファイルを比較しましたか? おそらく、Word 文書は zip ファイルよりも小さいため、すべてのファイルを 1 ステップで読み取ることができるため、2 番目の問題は実際には当てはまりません。

同じ (2 番目の) 問題は、ファイルを読み取るサーバーにも実際に当てはまります。

(およびサーバー側で DataOutputStream を)使用することを考えるかもしれません。DataInputStreamこれにより、Writer(および追加のバッファリング)を必要とせずに文字列を読み取ることもできます。

于 2011-02-10T12:23:13.797 に答える
0

内部IPで試しましたか?それも機能するはずであり、問​​題はインターネットからのNATまたはそのようなものだけです。

あなたのファイルでは、md5sums は同一ですか?

于 2011-02-10T11:52:39.627 に答える
0

リッスンしている IP を LAN IP に設定する必要があります。あなたが使用している127.0.0.1; localhost からのリクエストのみを受け付けます。

于 2011-02-10T12:12:24.963 に答える