0

ネットワークストリーム経由で画像を送信しようとしています.sendData関数とGetdata関数があり、Image.FromStream関数を使用すると常に無効なパラメータを取得します.

これは私のコードです:私は画面から写真を取得し、それをbyte []に​​変換して、ネットワークストリーム経由で送信するメモリストリームに挿入しています。

    private void SendData()
    {
        StreamWriter swWriter = new StreamWriter(this._nsClient);
        // BinaryFormatter bfFormater = new BinaryFormatter();

        // this method
        lock (this._secLocker)
        {
            while (this._bShareScreen)
            {
                // Check if you need to send the screen
                if (this._bShareScreen)
                {
                    MemoryStream msStream = new MemoryStream();
                    this._imgScreenSend = new Bitmap(this._imgScreenSend.Width,   this._imgScreenSend.Height);
                    // Send an image code
                    swWriter.WriteLine(General.IMAGE);
                    swWriter.Flush();

                    // Copy image from screen
                    this._grGraphics.CopyFromScreen(0, 0, 0, 0, this._sizScreenSize);
                    this._imgScreenSend.Save(msStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    msStream.Seek(0, SeekOrigin.Begin);

                    // Create the pakage
                    byte[] btPackage = msStream.ToArray();

                    // Send its langth
                    swWriter.WriteLine(btPackage.Length.ToString());
                    swWriter.Flush();

                    // Send the package
                    _nsClient.Write(btPackage, 0, btPackage.Length);
                    _nsClient.Flush();
                }
            }
        }
    }


    private void ReciveData()
    {
        StreamReader srReader = new StreamReader(this._nsClient);
        string strMsgCode = String.Empty;
        bool    bContinue = true;
        //BinaryFormatter bfFormater = new BinaryFormatter();
        DataContractSerializer x = new DataContractSerializer(typeof(Image));
        // Lock this method
        lock (this._objLocker)
        {
            while (bContinue)
            {
                // Get the next msg
                strMsgCode = srReader.ReadLine();

                // Check code
                switch (strMsgCode)
                {
                    case (General.IMAGE):
                        {
                            // Read bytearray
                            int nSize = int.Parse(srReader.ReadLine().ToString());
                            byte[] btImageStream = new byte[nSize];
                            this._nsClient.Read(btImageStream, 0, nSize);

                            // Get the Stream
                            MemoryStream msImageStream = new MemoryStream(btImageStream, 0, btImageStream.Length);

                            // Set seek, so we read the image from the begining of the stream
                            msImageStream.Position = 0;

                            // Build the image from the stream
                            this._imgScreenImg = Image.FromStream(msImageStream); // Error Here
4

2 に答える 2

1

簡潔にする: Stream.Read 関数 (使用する) は、読み取ったバイト数を示す int を返します。これが返されるので、必要なすべてのバイトが受信されたことを確認できます。何かのようなもの:

int byteCount=0;
while(byteCount < nSize)
{
      int read = this._nsClient.Read(btImageStream, byteCount, nSize-byteCount);
      byteCount += read;
}

これは仕事に最適なコードではありません

于 2012-08-31T06:11:39.717 に答える
1

問題の一部は、書き込みの最後に Environment.NewLine を追加する WriteLine() を使用していることです。反対側で Read() を呼び出すだけでは、その改行を適切に処理していません。

やりたいことは、ストリームに Write() してから、反対側で読み返すことです。

文字列への変換は奇妙です。

画像を転送するときに行っていることは、バイト配列を送信することです。必要なのは、予想されるストリームの長さを送信し、次に画像自体を送信し、反対側で長さとバイト配列を読み取ることだけです。

バイト配列をネットワーク経由で転送する最も基本的で単純な方法は、最初に配列の長さを表す整数を送信し、受信側でその長さを読み取ることです。

送受信するデータの量がわかったら、配列を生のバイト配列としてネットワーク上に送信し、反対側で以前に決定した長さを読み取ります。

生のバイトとサイズが得られたので、配列をバッファから有効な画像オブジェクト (または送信した他のバイナリ形式) に再構築できます。

また、その DataContractSerializer が存在する理由もわかりません。これは生のバイナリ データであり、とにかく手動でバイトにシリアライズしているため、これは役に立ちません。

ソケットとストリームを使用したネットワーク プログラミングの基本的な問題の 1 つは、プロトコルを定義することです。これは、受信側が、ストリームがいつ終了するか、または予期されることを認識できないためです。そのため、一般的なプロトコルはすべて、非常に厳密に定義されたパケット サイズとレイアウトを持っているか、長さ/データのペアを送信するなどの処理を行って、受信側が何をすべきかを認識しています。

配列の長さを表す整数を送信し、受信側で整数を読み取るなどの非常に単純なプロトコルを実装すると、目標の半分を達成したことになります。次に、送信者と受信者の両方が次に何が起こるかについて合意します。次に、送信者は正確にそのバイト数をネットワーク上で送信し、受信者は正確にそのバイト数をネットワーク上で読み取り、読み取りが終了したと見なします。これで、受信側の元のバイト配列の正確なコピーが得られ、最初にそのデータが何であったかを知っているので、それを好きなように処理できます。

コード例が必要な場合は、簡単なものを提供できます。そうでなければ、ネット上で多数の例を入手できます。

于 2012-08-31T03:33:49.900 に答える