2016-09-13 5 views
0

첫 번째 배경. 이더넷 케이블을 통해 내 앱이 연결되어있는 카메라를 가지고 있으며 명령을 기반으로 작업을 수행하고 명령을 보내면 응답합니다.스트림에서의 빠른 패킷 처리

예를 들어 카메라 트리거 명령을 사용합니다. 'T1'을 보내면 카메라가 사진을 찍습니다. 모든 명령은 내가이

(문자) 0x02T1 (문자) 0x03으로

모양을 보낼 전체 패킷 수 있도록 시작과 팩의 끝을 표시하기 위해 시작과 끝 문자를 사용하여 시작으로 (문자)는 0x02 팩의 끝으로 (char) 0x03.

카메라가 사진을 찍은 다음 동일한 명령을 보내면 완료되었다고 말합니다. 또한 사진을 촬영할 때 일부 데이터를 다시 보내도록 카메라를 설정할 수 있습니다. 제 경우에는 카메라를 몇 가지 영역을 검사하고 검사에서 일부 값을 원합니다.

그래서 카메라의 반환은 'T1'과 같이 될 것이라고 다음 문제에

을 '1,1,500,20,300'을 말한다. 나는 통신을 위해 TcpClientNetworkStream을 사용하고 있지만 수신 측에서 패킷을 처리하는 데 어려움을 겪고있다. 다양한 방법을 시도했지만 속도가 느려지거나 모든 데이터를 가져올 수 있다고 보장하지 않습니다.

먼저 모든 데이터를 읽고 모든 데이터가 있는지 확인해야합니다.

둘째, 데이터를 처리하고 패킷으로 분할하여 가능한 한 빨리 처리 할 수있는 무언가가 필요합니다.

이것은 내가 시도한 한 가지 방법 일 뿐이며 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

연결이 켜져 있습니까? 방화벽에 의해 차단 되었습니까? (다른 쪽) –