0

クライアントサーバーの状況で、クライアントがデータ(映画など)をサーバーに送信すると、サーバーはそのデータをHDDに保存します。

固定バイト配列でデータを送信します。バイトが送信された後、サーバーはさらに送信するかどうかを尋ねます。ある場合は、さらに送信します。すべてが順調に進んでおり、すべてのデータが行き渡っています。

しかし、映画を再生しようとすると再生できず、各映画(クライアントとサーバー)のファイル長を見ると、サーバー映画はクライアント映画よりも大きくなっています。最後にコマンド画面を見ると、送信/受信データの100%を超えるバイトがあります。

私が間違っていると思う唯一のことは、固定バッファー配列がいっぱいになるまでサーバーがストリームを読み取り、そのため、最後にクライアントよりも多くのバイトがあるという事実です。しかし、それが問題である場合、どうすればこれを解決できますか?

送信の2つの方法を追加しました。tcp接続が機能するため、どんな助けでも大歓迎です。

クライアント

public void SendData(NetworkStream nws, StreamReader sr, StreamWriter sw)
{
    using (FileStream reader = new FileStream(this.path, FileMode.Open, FileAccess.Read))
    {                
         byte[] buffer = new byte[1024];
         int currentBlockSize = 0;

         while ((currentBlockSize = reader.Read(buffer, 0, buffer.Length)) > 0)
         {
             sw.WriteLine(true.ToString());
             sw.Flush();
             string wait = sr.ReadLine();
             nws.Write(buffer, 0, buffer.Length);
             nws.Flush();
             label1.Text = sr.ReadLine();
         }
         sw.WriteLine(false.ToString());
         sw.Flush();                
    }
}

サーバ

    private void GetMovieData(NetworkStream nws, StreamReader sr, StreamWriter sw, Film filmInfo)
    {
        Console.WriteLine("Adding Movie: {0}", filmInfo.Titel);
        double persentage = 0;

        string thePath = this.Path + @"\films\" + filmInfo.Titel + @"\";
        Directory.CreateDirectory(thePath);

        thePath += filmInfo.Titel + filmInfo.Extentie;

        try
        {
            byte[] buffer = new byte[1024]; //1Kb buffer

            long fileLength = filmInfo.TotalBytes;
            long totalBytes = 0;

            using (FileStream writer = new FileStream(thePath, FileMode.CreateNew, FileAccess.Write))
            {
                int currentBlockSize = 0;
                bool more;
                sw.WriteLine("DATA");
                sw.Flush();
                more = Convert.ToBoolean(sr.ReadLine());


                while (more)
                {
                    sw.WriteLine("SEND");
                    sw.Flush();
                    currentBlockSize = nws.Read(buffer, 0, buffer.Length);
                    totalBytes += currentBlockSize;
                    writer.Write(buffer, 0, currentBlockSize);

                    persentage = (double)totalBytes * 100.0 / fileLength;
                    Console.WriteLine(persentage.ToString());

                    sw.WriteLine("MORE");
                    sw.Flush();
                    string test = sr.ReadLine();
                    more = Convert.ToBoolean(test);                       
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
4

2 に答える 2

2

読み取られたバイト数を返すのには理由がありRead()ます。バッファのサイズよりも小さい値を返す可能性があります。このため、のようなことをする必要がありnws.Write(buffer, 0, currentBlockSize);ますSendData()。ただし、ブロックのサイズがなくなるため、これによりプロトコルが破損します。

しかし、あなたのコードが実際にあなたが説明したように振る舞うとは信じがたいです。これは、Read()inGetMovieData()もバッファ全体をいっぱいにしない可能性があるためです。また、StreamReader一部のデータを内部バッファに保持することが許可されています。これは、完全に偽のデータを読み取ることができることを意味します。

StreamsとStreamReaders/ sを組み合わせるこのようなコードStreamWriterは本当に悪い考えだと思います。それを実際に正しくするのは難しいでしょう。代わりにすべきことは、それらのバイトがASCIIでエンコードされている場合でも、プロトコルを完全にバイトベース(文字ベースではない)にすることです"SEND"

于 2012-06-14T09:54:12.070 に答える
0

試してみましょうが、うまくいかない場合は撃たないでください

送信するファイルに残っているバイト数に関係なく、バッファサイズは1024であることがわかります。2900バイトのファイルがあり、3回送信する必要があるとします。最後に送信すると、送信できるのは852バイトだけになります。ただし、1024のバッファを作成し、1024バイト以上を送信します。これは、サーバーが852バイトの実データと172バイトのゼロで埋められたバイトを受信することを意味します。ただし、これらの172バイトはすべてサーバー上のムービーファイルに保存されます。

簡単な修正があると思います。サーバーにデータを書き込むときはcurrentBlockSize、長さの引数としてasを使用します。したがってSendData、クライアントのメソッドで、whileループ内で次のように変更します。

nws.Write(buffer, 0, buffer.Length);

これに:

nws.Write(buffer, 0, currentBlockSize);
于 2012-06-14T09:56:31.130 に答える