2016-09-13 14 views
0

最初の背景。私は、私のアプリがイーサネットケーブルを介して接続されているカメラを持っていて、それは送信したコマンドに基づいて操作を実行し、コマンドで返信します。ストリームからの高速パケット処理

例としてカメラのトリガーコマンドを使用します。 「T1」を送信すると、カメラで写真が撮影されます。すべてのコマンドは、スタートとして、私が送っフルパケットが(文字)が0x02でこの

(CHAR)0x02T1(文字)0x03の

のようになりますので、パックの開始と終了をマークするために、開始と終了文字を使用しますパケットの(char)0x03をパックの最後とします。

カメラが写真を撮影し、同じコマンドを送り返して終了します。また、画像を撮影したときにデータを戻すようにカメラを設定することもできます。私の場合、私はカメラがいくつかの領域を検査しており、検査からいくつかの値が必要です。

ので、カメラのリターンは、「T1」のようなものにし、問題への「1,1,500,20,300」

を言うでしょう。私は通信のためにTcpClientNetworkStreamを使用していますが、私は受信側でパケットを処理するのに苦労しています。私は様々な方法を試しましたが、遅くなったり、すべてのデータを取得する保証はありません。

まず、すべてのデータを読み、すべてのデータがあることを確認する必要があります。

第2に、データを処理してパケットに分割し、可能な限り高速に処理できるものが必要です。

これは私が試した1つの方法であり、StreamReaderExtensionsを作った人に全額のクレジットが送られます。私はどこかでここでそれを見つけたと確信しています。

internal static class StreamReaderExtensions 
{ 
    public static IEnumerable<string> ReadUntil(this StreamReader reader, string delimiter) 
    { 
     List<char> buffer = new List<char>(); 
     CircularBuffer<char> delim_buffer = new CircularBuffer<char>(delimiter.Length); 

     while (reader.Peek() >= 0) 
     { 
      char c = (char)reader.Read(); 
      delim_buffer.Enqueue(c); 
      if (delim_buffer.ToString() == delimiter) 
      { 
       if (buffer.Count > 0) 
       { 
        yield return new String(buffer.ToArray()); 
        buffer.Clear(); 
       } 
       continue; 
      } 
      buffer.Add(c); 
     } 
    } 

    private class CircularBuffer<T> : Queue<T> 
    { 
     private int _capacity; 

     public CircularBuffer(int capacity) 
      : base(capacity) 
     { 
      _capacity = capacity; 
     } 

     new public void Enqueue(T item) 
     { 
      if (base.Count == _capacity) 
      { 
       base.Dequeue(); 
      } 
      base.Enqueue(item); 
     } 

     public override string ToString() 
     { 
      List<String> items = new List<string>(); 
      foreach (var x in this) 
      { 
       items.Add(x.ToString()); 
      }; 
      return String.Join("", items); 
     } 
    } 
} 

と私の処理方法。 _stream

public static class Constants 
{ 
    public const char StartOfPacket = (char)0x02; 
    public const char EndOfPacket = (char)0x03; 
} 

private IEnumerable<string> ProcessResponse() 
{ 
    var streamReader = new StreamReader(_stream); 
    var packets = streamReader.ReadUntil(new string(new char[] {Constants.EndOfPacket})); 
    return packets; 
} 
+0

あなたはcharごとに読んでください。大きなブロックを読み、受信したサイズを確認するだけです。区切り文字を見つけて解析されたブロックを削除するまでブロックを解析します。パケットが半分になるまで繰り返します。 –

+0

@JeroenvanLangenハーフパケット? – Gaz83

+0

より多くの受信/パケットでメッセージを分割することができます。これは、データグラムの代わりにストリームであるためです。当時は1文字しか受け取られていない場合は、常に複数の受信で分割されています。 –

答えて

0

TcpClient.GetStream()は、私は、私はそれをテストしていなかったために、いくつかの擬似コードを作ったが、それはあなたの方向性を与えるかもしれません。 これは

char[] _buffer = new char[4 * 1024 * 1024]; 
int currentPosition; 

public bool ReadNext(StreamReader reader, char delimiter, out string value) 
{ 
    // read as many chars from the stream. 
    int charsRead = reader.ReadBlock(_buffer, currentPosition, _buffer.Length - currentPosition); 

    // keep track of the current position. 
    currentPosition += charsRead; 

    // find the first delimiter. 
    for (int i = 0; i < currentPosition; i++) 
    { 
     if (_buffer[i] == delimiter) 
     { 
      // a complete packet was found, copy it to a string. 
      value = new string(_buffer, 0, i); 
      // move the rest of the data back to the start of the buffer. 
      Array.Copy(_buffer, i, _buffer, 0, _buffer.Length - i); 
      // decrease the current position also. 
      currentPosition -= i; 
      // return true because you have data. 
      return true; 
     } 
    } 

    // no complete packet was found. 
    value = String.Empty; 
    return false; 
} 

使用静的することはできません:私はテストされていないを言ったように

string data; 

while(true) 
{ 
    if(ReadNext(reader, (char)0x03, out data)) 
     MessageBox.Show(data); 
} 

、これは単なるbrainfartです...あなたは、のチェックを追加する必要がありますパケットの開始。

+0

ありがとう。私はそれを見て、それを試してみます。 – Gaz83

+0

これを試してみるだけで何らかの理由で私は "System.IO"を手に入れました。"ReadBlock"を実行しているときに "例外"が発生しました 内部例外では、接続されたパーティが一定時間が経過した後に正しく応答しなかったために接続できませんでした... 同じストリームへの書き込みが正常に行われました – Gaz83

+0

接続は(相手側) –

関連する問題