2012-01-12 28 views
0

小さな画像を送受信するウェブカメラアプリを作っています。私はそれを送受信できるようにしました。私は127.0.0.1でテストしましたが、うまくいきましたが、今は自分の外部IPアドレスを使用しています。画像を1つ送信して受信してしまいましたイメージサイズの大規模な整数値の何らかの並べ替え、それがクラッシュにつながるマイナスの値、私は多分受信と送信が自分自身で実行されていると思うし、何とか同期が外れている。私は各画像を送信する前に1000msの遅延を入れて、それは遅いが働いていた、私が遅延を取り除くとすぐに、それはうんざりする。TCPパケット送信エラー

// This sends. 
    private void NewFrameReceived(object sender, NewFrameEventArgs e) 
    { 
     Bitmap img = (Bitmap)e.Frame.Clone(); 

     byte[] imgBytes = EncodeToJpeg(img, 25).ToArray(); 
     if (_tcpOut.Connected) 
     { 
      NetworkStream ns = _tcpOut.GetStream(); 
      if (ns.CanWrite) 
      { 
       System.Threading.Thread.Sleep(500); 
       ns.Write(BitConverter.GetBytes(imgBytes.Length), 0, 4); 
       ns.Write(imgBytes, 0, imgBytes.Length); 
      } 
     } 
    } 

    // This receives. 
    private void listeningThread_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
     // start listening for connections 
     _tcpIn = new TcpListener(IPAddress.Any, 54321); 
     _tcpIn.Start(); 

     TcpClient _inClient = _tcpIn.AcceptTcpClient(); 
     while (true) 
     { 
      NetworkStream ns = _inClient.GetStream(); 
      if (ns.CanRead && ns.DataAvailable) 
      { 
       Byte[] imgSizeBytes = new Byte[4]; 
       ns.Read(imgSizeBytes, 0, 4); 
       int imgSize = BitConverter.ToInt32(imgSizeBytes, 0); 

       Byte[] imgBytes = new Byte[imgSize]; <-- ERROR, GET CRAZY LARGE VALUE 
       ns.Read(imgBytes, 0, imgSize); 

       MemoryStream ms = new MemoryStream(imgBytes); 
       Image img = Image.FromStream(ms); 

       picVideo.Image = img; 
      } 
     } 
    } 
+0

あなたは例外を投稿できますか? –

+0

こんにちは、時々私は "算術演算はオーバーフローの結果となります。"メモリオーバーフローが発生することがあります。 (また、エラーラインは下の行に修正されました) – sprocket12

+0

あなたの質問に適切に答えるには、変数と未知数が多すぎます。最初のステップとして、最初の送信から何バイトが実際に受信されているかを確認し、送信されているものと一致することを証明することをお勧めします。画像の大きさに応じて、送信されるデータの断片化にぶつかる可能性があります。 –

答えて

1

Readあなたが求めているバイト数は必ずしも多くのバイト数であるとは限りません。実際には現在利用可能な数が多くあります。 documentationは、より理解を深めるのに役立ちます。

すべてのイメージバイトが読み取られるまで、読み取りを維持するロジックを追加する必要があります。疑似コードの例:

total_bytes_read = 0; 
while (total_bytes_read != total_bytes_needed) 
{ 
    bytes_left_to_read = total_bytes_needed - total_bytes_read; 
    total_bytes_read += read(buffer, total_bytes_read, bytes_left_to_read); 
} 
3

あなたは少し.....データが異なるパケットで到着する可能性物事を再考する必要があります。ここでは

はコードです。あなたの読み込み機能は、利用可能なものだけを読み込みます。これにより、システムの同期が外れることになります。

私はいつも画像の開始と終了がデータストリームのどこにあるのかを知ることができるように、画像用のプロトコルを少し作成します。

あなたはそれをする必要はありませんが、それは人生を楽にします。純粋に単純なステートマシンで行うことができます。しかし、画像を送信することに従わない場合(例えば、ストリーム内に余分な1バイトがある場合)、永遠に同期を外すことができます。

+0

貴重なご意見ありがとうございます。しかし、何らかの「マーカー」バイトを追加すると、1024バイトというブロックの真ん中に来て、古い画像が終了し、新しい画像が開始されたことをどのように知ることができますか?受信した1024バイトブロックの各バイトを調べて、特別な終了フラグをチェックする必要がありますか?バイト配列データの結合操作と検索操作に最適なクラスはどれですか? – sprocket12

+1

多くの場合、エスケープシーケンスを使用してブロックデータから開始/終了制御文字を削除する方法があります。もう1つの方法はブロック長にブロック長を含むヘッダーを付けることで、rxがブロック全体を受信した時点を判断して別のヘッダーを探し始めることができます。ヘッダーには、ヘッダーの健全性をチェックするための十分なデータと冗長性が必要です(たとえば、常に[SOH]で始まり、データ長とCRCを固定長のASCII数字形式で含む)。 rxにバイトバイバイステートマシンが必要な場合があります。ヘッダーを確認します。 –