2012-10-14 5 views
0

포트를 청취하고 일부 패킷을 수신하는 응용 프로그램을 작성했습니다. 사용자 정의 된 프로토콜에 따르면 패킷 길이는 49 바이트에서 1500 바이트까지입니다. 패킷. 49 바이트 패킷과 더 큰 패킷의 데이터를 해석하고 처리해야하는 방식이 다릅니다.TCP 클라이언트에서 데이터를 수신 할 때 오류가 발생했습니다.

문제는 내가 1374 바이트 미만의 패킷을 모두 받았을 때 패킷의 길이가 길어지면 다음 예외가 발생하고 내 데이터의 마지막 4 바이트가 손실된다는 것입니다. 1384byte 패킷 및 마지막 4 바이트 손실)

제기 된 예외 : 인덱스가 범위를 벗어났습니다. 음수가 아니어야하며 콜렉션의 크기보다 작아야합니다. 매개 변수 이름 : startIndex

각 49 바이트 패킷에는 35 바이트의 데이터가 있으며 더 큰 패킷의 데이터 길이는 (압축으로 인해) 비 결정적입니다.

마지막 4 바이트가 별도의 "바이트"및 "결과"변수에 있음을 알았습니다. 즉, 새 패킷처럼 취급되고 해당 패킷에 연결되어 있지 않음을 의미합니다. 여기

데이터 수신에 대한 코드입니다 : 그렉 제안 및 나의 연구에 따르면

TcpClient Client = obj as TcpClient; 
     EndPoint ep = Client.Client.RemoteEndPoint; 
     List<Byte> result = new List<byte>(); 
     result.Capacity = 2000; 
     try 
     { 


      NetworkStream stream = Client.GetStream(); 
      int i = 49; 
      while ((i = stream.Read(bytes, 0,49)) != 0) 
      { 

       for (int id = 0; id < i; id++) 
       { 
        result.Add(bytes[id]); 
       } 
//reading data length to determine packet length 
       byte[] tmp = new byte[2]; 
       tmp = BitConverter.GetBytes(BitConverter.ToUInt16(result.ToArray(), 9)); 
       if (BitConverter.IsLittleEndian) 
       { 
        Array.Reverse(tmp); 
       } 
       Int16 l = BitConverter.ToInt16(tmp, 0); 
       if (l>35) 
       { 
        stream.Read(bytes, result.Count, l - 35); 
        for (int id = 49; id <((l-35)+49); id++) 
        { 
         result.Add(bytes[id]); 
        } 
        if (this.TCPDataReceivedHandler != null) 
        { 
         this.TCPDataReceivedHandler(ep, result.Count, result.ToArray()); 
         result.Clear(); 
         Array.Clear(bytes, 0, 2000); 
         result.Capacity = 2000; 
        } 
       } 
       else 
       { 
        if (this.TCPDataReceivedHandler != null) 
        { 
         this.TCPDataReceivedHandler(ep, result.Count, result.ToArray()); 
         result.Clear(); 
         Array.Clear(bytes, 0, 2000); 
         result.Capacity = 2000; 
        } 
       } 


      } 
      System.Diagnostics.Debug.WriteLine("client Close"); 
      Client.Close(); 

     } 
     catch (System.Exception ex) 
     { 
      throw ex; 
     } 
     finally 
     { 
      Client.Close(); 
      this.clients.Remove(Client); 
     } 

을, 나는 또한 다음과 같은 방법을 사용하여 시도 : TCP를 사용하는 경우

NetworkStream stream = Client.GetStream(); 
      int bytesread = 0, OffsetTemp = 0; 

      while (stream.CanRead) 
      { 
       OffsetTemp = 0; 

       bytesread += stream.Read(bytess, OffsetTemp, 11); 
       OffsetTemp = OffsetTemp + 11; 



       byte[] tmp = new byte[2]; 
       tmp = BitConverter.GetBytes(BitConverter.ToUInt16(bytess.ToArray(), 9)); 
       if (BitConverter.IsLittleEndian) 
       { 
        Array.Reverse(tmp); 
       } 
       Int16 l = BitConverter.ToInt16(tmp, 0); 

       bytesread += stream.Read(bytess, OffsetTemp++, 11 + l + 3); 
       for (int id = 0; id < l + 14; id++) 
       { 
        result.Add(bytess[id]); 
       } 

       if (this.TCPDataReceivedHandler != null) 
       { 
        this.TCPDataReceivedHandler(ep, result.Count, result.ToArray()); 
        result.Clear(); 
        Array.Clear(bytess, 0, 2000); 
       } 

      } 

답변

0

, 당신이 명심해야 당신이 넣는 데이터 블록의 크기는 입니다.은받는 쪽에서 나가는 데이터 블록의 크기와 같을 수 없습니다. TCP는 스트림 프로토콜이므로 동일한 바이트가 전송 된 순서와 동일한 순서로 상대방에게 전달되도록 보장합니다 (그렇지 않은 경우 소켓 연결이 재설정 됨). TCP는 send()에 대한 호출간에 블록 경계를 유지하지 않으며 네트워크 상태에 따라 블록을 임의로 분할하거나 병합 할 수 있습니다.

수신자가 에 대한 통화에서 어떤 양의 데이터 수신을 처리 할 수 ​​있도록 준비해야하지만 사용자 코드는이를 수행하지 않습니다. 예를 들어, 정확하게 작성된 수신기 코드는 이 한 번에 하나만 바이트 만 수신하더라도 계속 올바르게 작동해야합니다.

+0

고마워,하지만 내 패킷의 데이터 길이 필드에주의하지 않고 stream.Read()에서 계속 읽으면 패킷이 서로 섞이지 않는 것을 어떻게 확인할 수 있습니까? 패킷이 단시간에 연속적으로 전송됩니다. –

+0

프로토콜에 다음과 같은 데이터 블록의 길이를 지정하는 헤더가있는 것 같습니다. 따라서 현재 블록에 대해 그 정도만 읽은 다음 상단으로 돌아가 다음 블록의 길이 헤더를 읽습니다. –

+0

친애하는 그렉, 나는 당신의 제안을 사용했지만 작동하지 않았지만 여전히 1380 바이트 이상의 데이터를 수신하는 데 문제가 있습니다. –

관련 문제