2

私はクライアントサーバーを作っています。サーバーはハードコードされたファイルを送信できますが、クライアントは指定されていません。テキストファイルのみを送信する必要があります。私が理解している限り、クライアントは最初にファイル名を送信し、次にサーバーがそれを送信します。複雑なことは何もありませんが、あらゆる種類のエラーが発生しています。このコードは接続リセット/ソケットクローズエラーを取得しています。主な問題は、ネットワーキングを研究する時間があまりなかったことです。

私が得ることができるどんな助けにも感謝します。

編集。 回避策を見つけました。ストリームを閉じるとソケットが閉じます。なぜですか? あってはならないことですよね?

サーバ側:

    InputStream sin=newCon.getInputStream();
    DataInputStream sdata=new DataInputStream(sin);
    location=sdata.readUTF();   
    //sdata.close();
    //sin.close();

File toSend=new File(location);
byte[] array=new byte[(int)toSend.length()];
FileInputStream fromFile=new FileInputStream(toSend);
BufferedInputStream toBuffer=new BufferedInputStream(fromFile);
toBuffer.read(array,0,array.length);

OutputStream out=newCon.getOutputStream(); //Socket-closed...
out.write(array,0,array.length);
out.flush();
toBuffer.close();
newCon.close();

クライアント側:

int bytesRead;
server=new Socket(host,port);

OutputStream sout=server.getOutputStream();
DataOutputStream sdata=new DataOutputStream(sout);
sdata.writeUTF(interestFile);
//sdata.close();
//sout.close();

InputStream in=server.getInputStream();     //socket closed..
OutputStream out=new FileOutputStream("data.txt");
byte[] buffer=new byte[1024];
while((bytesRead=in.read(buffer))!=-1)
{
    out.write(buffer,0,bytesRead);
}
out.close();
server.close();
4

1 に答える 1

1

一時バイト配列を作成してファイル全体をメモリに読み込むのではなく、クライアント出力ストリームへの書き込み中にサーバーからファイルをチャンクで読み取るようにしてください。要求されたファイルが大きい場合はどうなりますか? また、finally ブロックでサーバー側の新しい Socket を閉じて、例外がスローされた場合でもソケットが閉じられるようにします。

サーバ側:

    Socket newCon = ss.accept();
    FileInputStream is = null;
    OutputStream out = null;
    try {
        InputStream sin = newCon.getInputStream();
        DataInputStream sdata = new DataInputStream(sin);
        String location = sdata.readUTF();
        System.out.println("location=" + location);
        File toSend = new File(location);
        // TODO: validate file is safe to access here
        if (!toSend.exists()) {
            System.out.println("File does not exist");
            return;
        }
        is = new FileInputStream(toSend);
        out = newCon.getOutputStream();
        int bytesRead;
        byte[] buffer = new byte[4096];
        while ((bytesRead = is.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        out.flush();
    } finally {
        if (out != null)
            try {
               out.close();
            } catch(IOException e) {
            }
        if (is != null)
            try {
               is.close();
            } catch(IOException e) {
            }
        newCon.close();
    }

Apache Common IOUtilsライブラリを使用すると、ファイルをストリームに読み書きするコードの多くを減らすことができます。ここでは、5 行を 1 行に減らします。

org.apache.commons.io.IOUtils.copy(is, out);

リモートクライアントへの絶対パスでファイルを提供するサーバーを持つことは潜在的に危険であり、ターゲットファイルは特定のディレクトリおよび/または一連のファイルタイプに制限する必要があることに注意してください。認証されていないクライアントにシステム レベルのファイルを提供したくない。

于 2012-12-22T01:35:06.893 に答える