2

サーバーとクライアント間のファイル転送コードの簡単な例を書き直しました。

そしてそれは動作します。

しかし、特定のディレクトリにある複数のファイルを転送できるようにしたいのです。ユーザーはファイル名(その特定のディレクトリにあります)を書き込み、クライアントはそれらをサーバーからダウンロードします。どうやってやるの?何か案は?ありがとうございました。

クライアントコード:

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

    public class Client {

        static String hostname = "127.0.0.1";
        static int port = 4588;
        static int processedByte; 
        static byte[] theByte = new byte[1];

        static Socket client = null; 
          static InputStream inuputSt = null; 

        public static void main(String[] args) throws InterruptedException {
            System.out.println("connecting...");
            Thread.sleep(500);
            try { 
                client = new Socket(hostname, port); 
                inuputSt = client.getInputStream(); 
            } catch (IOException ex) { 
                System.out.println("connection error.");
            } 

            ByteArrayOutputStream arrayOutput = new ByteArrayOutputStream(); 

            if (inuputSt != null) { 

                FileOutputStream fileOutput = null; 
                BufferedOutputStream bufferedOutput = null; 
                try { 
                    System.out.println("downloading target file...");
                    Thread.sleep(800);
                    fileOutput = new FileOutputStream("file1_downloaded.txt"); 
                    bufferedOutput = new BufferedOutputStream(fileOutput); 
                    processedByte = inuputSt.read(theByte, 0, theByte.length); 

                    do { 
                            arrayOutput.write(theByte); 
                            processedByte = inuputSt.read(theByte); 
                    } while (processedByte != -1); 

                    bufferedOutput.write(arrayOutput.toByteArray()); 
                    bufferedOutput.flush(); 
                    bufferedOutput.close(); 
                    System.out.println("file downloaded");
                    client.close(); 
                } catch (IOException ex) { 
                    System.out.println("file transfer error."); 
                } 
            }

        }
    }

サーバーコード:

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

public class Server {
static int port = 4588;
public static void main(String[] args) {

    while (true) {
        ServerSocket server = null; 
        Socket connection = null; 
        BufferedOutputStream bufferedOutput = null; 

        try { 
            server = new ServerSocket(port); 
            connection = server.accept(); 
            bufferedOutput = new BufferedOutputStream(connection.getOutputStream()); 
        } catch (IOException ex) { 
            // Do exception handling 
        } 

        if (bufferedOutput != null) { 
            File fileToSend = new File("files\\file1.txt"); 
            byte[] mybytearray = new byte[(int) fileToSend.length()]; 

            FileInputStream fileInputSt = null; 

            try { 
                fileInputSt = new FileInputStream(fileToSend); 
            } catch (FileNotFoundException ex) { 
                // exception stuff
            } 
            BufferedInputStream bufferedInput = new BufferedInputStream(fileInputSt); 

            try { 
                bufferedInput.read(mybytearray, 0, mybytearray.length); 
                bufferedOutput.write(mybytearray, 0, mybytearray.length); 
                bufferedOutput.flush(); 
                bufferedOutput.close(); 
                connection.close(); 

                //file1.txt has been downloaded
                return; 
            } catch (IOException ex) { 
                // exception stuff
            } 
        } 
    } 
}

}
4

3 に答える 3

2

あなたはクライアントとサーバーのプロトコルとして HTTP を提案しています。HTTPPUT動詞を使用してファイルをアップロードできます。この方法で HTTP を使用する利点は、クライアントとサーバーが、PUT要求を使用するように設計された他のツールと通信できることです。(PUTは他の HTTP 動詞よりもあまり使用されないため、すべての HTTP ツールが機能するとは限りません。プログラムはcurl(1)コマンドライン オプションを介してサポートします。HTTP を選択した場合、これは実装の大きな助けになります。)PUT-T

HTTP ソフトウェアの作成に役立つさまざまなREST フレームワークがあります。Restletについて良いことを聞いたことがあります。それは私の推奨される出発点です。

ただし、HTTP をプロトコルとして選択する必要はありません独自のプロトコルを実装すれば、ネットワーク プログラミングについて多くのことを学べると思います。事前に作成された HTTP プロトコル ツールを使用して学習するのは難しい方法で、API 設計とソケット プログラミングについて多くのことを学ぶことができます (そしてイライラすることもあります)。 HTTP 全体を自分で実装しようとした場合)。

この会話を考えてみましょう:

クライアント -> サーバー: サイズが 200000 バイトの "flubber" という名前のファイルをアップロード
サーバー -> クライアント: OK
クライアント -> サーバー: Flubber コンテンツ
サーバー -> クライアント: OK
クライアント -> サーバー: サイズが 10 バイトの "blort" という名前のファイルをアップロード
サーバー ->クライアント: エラー、ファイルが存在し
ます...

ファイル転送が成功したことを確認するために両端でファイルをハッシュするための新しいコマンド、特定のバイト範囲を送信するためのコマンド (既存のファイルに追加するか、失敗した転送を再開するためのコマンド)、既存のリストを一覧表示するコマンドを追加することができます。サーバー上のファイル名、既存のファイルを上書きするコマンド、サーバーからファイルを削除するコマンドなどです。独自のプロトコルを作成する最大の利点は、プログラムが何をサポートするかを決定できることです。欠点は、作成した機能をテストできることであり、場合によってはテストが難しい場合があります。(たとえば、クライアントがコマンドの各文字を別の TCP パケットで送信するとします。コマンド全体を格納するためのバッファリングの実装は簡単ではありませんが、Restlet などのツールを使用して既に実行されています。)

複数の TCP セッションを使用するという Juan のアドバイスは厳密には必要ではありません。ファイル名をリモート ピアに提供するためのメカニズムを追加する必要があります。これは、「コントロール」チャネル (最初に実行されるセッション -- FTP と同様) を介して行うのが最適な場合もあれば、ファイルの内容 (HTTP と同様)。

ただし、複数の接続を避けることをお勧めします。各接続では、システム間のラウンドトリップ時間をセットアップしてバイト転送を開始するのに 3 倍の時間が必要です。この遅延は、特に何百もの小さなファイルを転送しようとしている場合に、非常に煩わしい場合があります。実際にデータを送信するよりも、接続のセットアップに多くの時間を費やすことさえできます。

しかし、それはあなたのツールです。あなたが望むようにデザインすることができます。楽しむ。

于 2012-05-17T23:00:23.583 に答える
1

そのような状況でファイルを同時に転送できるように、ファイルごとに新しい接続を作成する必要があると思います。

サーバーを変更して、クライアント接続ごとに新しいスレッドを作成する(またはスレッドプールからスレッドプールから取得する)必要がある場合があります。これにより、サーバーは同時に多数のスレッドで動作できるようになります。

次に、ファイルごとに1回クライアントを実行できます。

乾杯

于 2012-05-17T00:06:07.980 に答える
1

OK、ArrayListまたはListファイルを作成して複数のファイルを転送できますか。ファイルシステム パスに出た後、アレイに入る。お役に立てれば幸いです。

于 2012-05-17T00:30:19.450 に答える