문제

네트워크 스트림에서 읽고있는 바이트 배열이 있습니다. 처음 두 바이트는 다음과 같은 패킷의 길이를 알리고 패킷은 그 길이의 바이트 배열로 읽습니다. NetworkStream/Byte 배열에서 읽어야한다는 데이터에는 몇 가지 문자열, 즉 새로운 라인 문자로 종료 된 가변 길이 데이터 및 바이트 및 길이와 같은 고정 너비 필드가 있습니다. 그래서 다음과 같은 것 :

// I would have delimited these for clarity but I didn't want
// to imply that the stream was delimited because it's not.
StringbyteStringStringbytebytebytelonglongbytelonglong

나는 나오는 데이터 패킷의 형식을 알고 있으며, 내가해야 할 일은 각 문자열 값에 대해 "줄"을 읽는 것이지만 바이트와 긴에 대한 고정 된 수의 바이트를 읽는 것입니다. 지금까지 내 제안 된 솔루션은 while 루프 루프 바이트를 Newline 캐릭터가있을 때까지 임시 바이트 어레이로 읽습니다. 그런 다음 바이트를 문자열로 변환하십시오. 이것은 나에게 kludgy처럼 보이지만, 나는 또 다른 명백한 방법을 보지 못한다. 나는 내가 사용할 수 있다는 것을 알고있다 StreamReader.ReadLine() 그러나 그것은 다른 스트림과 관련이 있고 나는 이미 NetworkStream. 그러나 그것이 더 나은 해결책이라면, 나는 그것을 촬영할 것이다.

내가 고려한 다른 옵션은 백엔드 팀이 해당 문자열 값의 길이에 대해 바이트를 작성하도록하여 길이를 읽은 다음 지정된 길이를 기준으로 문자열을 읽을 수 있도록하는 것입니다.

보시다시피, 나는 이것에 대한 방법에 대한 몇 가지 옵션이 있으며, 최선의 방법을 고려할 것에 대한 의견을 원합니다. 전체 패킷에서 문자열로 읽기 위해 지금 가지고있는 코드는 다음과 같습니다. 다음 단계는 패킷의 다양한 필드를 세분화하고 수행 해야하는 실제 프로그래밍 작업, 객체 생성, UI 업데이트 등 패킷의 데이터를 기반으로하는 것입니다.

string line = null;  
while (stream.DataAvailable)
{  
    //Get the packet length;  
    UInt16 packetLength = 0;  
    header = new byte[2];  
    stream.Read(header, 0, 2);  
    // Need to reverse the header array for BitConverter class if architecture is little endian.  
    if (BitConverter.IsLittleEndian)
        Array.Reverse(header);  
    packetLength = BitConverter.ToUInt16(header,0);

    buffer = new byte[packetLength];
    stream.Read(buffer, 0, BitConverter.ToUInt16(header, 0));
    line = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
    Console.WriteLine(line);
}
도움이 되었습니까?

해결책

개인적으로 나는 할 것이다

  1. 문자열의 시작 부분에 Int16을 넣으므로 그들이 얼마나 오래 될지 알게됩니다.
  2. io.binaryReader 클래스를 사용하여 읽기를 수행하십시오. "읽기", ints, 문자열, 숯 등을 변수로 표시합니다. 개울

도움이 되었기를 바랍니다.

추신 : readString 메소드를 사용하여주의를 기울이면 문자열이 BinaryWriter 클래스에서 작성한 사용자 정의 7 비트 정수로 선불되었다고 가정합니다. 다음은 이것입니다 코드 구루 게시하다

BinaryWriter 클래스에는 문자열을 쓰는 두 가지 방법이 있습니다 : Overloaded Write () 메소드와 Writestring () 메소드. 전자는 클래스가 사용하는 인코딩에 따라 바이트 스트림으로 문자열을 씁니다. writestring () 메소드는 지정된 인코딩도 사용하지만 문자열의 실제 길이로 문자열의 바이트 스트림을 접두사합니다. 이러한 접두사 문자열은 BinaryReader.ReadString ()을 통해 다시 읽습니다.

길이 값에 대한 흥미로운 점은 가능한 적은 바이트 가이 크기를 유지하는 데 사용되며 7 비트 인코딩 된 정수라고하는 유형으로 저장됩니다. 길이가 7 비트로 맞는 경우 단일 바이트가 사용되는 경우,이보다 큰 경우 첫 번째 바이트의 높은 비트가 설정되고 값을 7 비트로 이동시켜 두 번째 바이트가 생성됩니다. 이것은 값을 유지하기에 충분한 바이트가있을 때까지 연속 바이트로 반복됩니다. 이 메커니즘은 길이가 직렬화 된 문자열에 의해 취해진 크기의 상당 부분이되지 않도록하는 데 사용됩니다. BinaryWriter와 BinaryReader는 7 비트 인코딩 된 정수를 읽고 쓰는 방법이 있지만 보호되어 있으므로이 클래스에서 파생 된 경우에만 사용할 수 있습니다.

다른 팁

나는 길이를 조정 한 줄로 갈 것입니다. 그것은 당신의 삶을 훨씬 더 단순하게 만들 것이며, 당신은 당신이 줄이 끊어진 줄을 나타내는 것을 의미합니다. 코드에 대한 몇 가지 의견은 다음과 같습니다.

  • stream.DataaVailable을 사용하지 마십시오. 사용 가능한 데이터가 없기 때문입니다 지금 스트림의 끝을 읽는 것을 의미하지는 않습니다.
  • ASCII 이외의 텍스트가 필요하지 않다고 확신하지 않으면 Asciiencoding을 사용하지 마십시오.
  • Stream.Read가 요청한 모든 데이터를 읽을 것이라고 가정하지 마십시오. 언제나 반환 값을 확인하십시오.
  • BinaryReader는 이것을 훨씬 쉽게 만듭니다 (길이가 정해진 문자열과 요청한 내용을 읽을 때까지 루프를 읽는 읽기 포함).
  • 동일한 데이터에서 bitconverter.touint16을 두 번 호출합니다. 왜요?
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top