2010-06-15 3 views
0

저는 현재 C# XNA로 만든 게임을하고 있습니다. 그물 (거친 96kb)를 통해 거대한 데이터 덩어리를 보내야하기 때문에 인터넷에서 찾은 일부 문자열 압축기/압축 해제 코드를 사용하고 있습니다. 코드는 다음과 같습니다인덱스가 "int msgLength = BitConverter.ToInt32 (gzBuffer, 0);"에서 범위를 벗어났습니다.

 public static string Compress(string text) 
    { 
     byte[] buffer = Encoding.UTF8.GetBytes(text); 
     MemoryStream ms = new MemoryStream(); 
     using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true)) 
     { 
      zip.Write(buffer, 0, buffer.Length); 
     } 

     ms.Position = 0; 
     MemoryStream outStream = new MemoryStream(); 

     byte[] compressed = new byte[ms.Length]; 
     ms.Read(compressed, 0, compressed.Length); 

     byte[] gzBuffer = new byte[compressed.Length + 4]; 
     System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length); 
     System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4); 

     return Convert.ToBase64String(gzBuffer); 
    } 

    public static string Decompress(string compressedText) 
    { 
     byte[] gzBuffer = Convert.FromBase64String(compressedText); 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      int msgLength = BitConverter.ToInt32(gzBuffer, 0); 
      ms.Write(gzBuffer, 4, gzBuffer.Length - 4); 

      byte[] buffer = new byte[msgLength]; 

      ms.Position = 0; 
      using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress)) 
      { 
       zip.Read(buffer, 0, buffer.Length); 
      } 

      return Encoding.UTF8.GetString(buffer); 
     } 
    } 

그것은 다음과 같이 작동 - 서버 위치를 클라이언트로 전송 한 후, 문자열 압축기를 사용하여 문자열을 압축합니다. - 클라이언트가 압축 된 문자열을 수신하고 압축을 풀어 사용할 수 있도록합니다.

이상한 부분은 게임을 혼자 테스트 할 때 코드가 작동한다는 것입니다. 즉, 동일한 컴퓨터에서 서버와 클라이언트를 실행한다는 의미입니다. 친구와 테스트를하고있을 때, 그가 서버를 호스팅하고 연결할 때도 작동합니다. 하지만 서버를 호스팅 할 때 내 친구가 작동하지 않고 연결됩니다. 그는 내 서버에 연결할 때 "int msgLength = BitConverter.ToInt32 (gzBuffer, 0);"에서 "Index out of range"를받습니다. 가끔은 운이 좋으면 도착하지만 대부분 실패하고 그 오류를 반환합니다. 서버가 전체 문자열을 보내지 못하게 할 수 있습니까? 네트워크 전송을 위해 Lidgren gen3을 사용 중이며 압축 된 문자열은 netMsg.Write (compressedstring);

모든 아이디어 :)? 감사합니다.

+0

스틱 a Debug.Assert (gzBuffer.Length> = 4); BitConverter.ToInt32()를 호출하기 전에 줄을 보면 문제가 표시됩니다. gzBuffer에는 Int32를 읽는 데 필요한 4 바이트도 포함되어 있지 않습니다. –

답변

2

동일한 가정을 여러 곳에서 잘못하고 있습니다. 즉, Stream.Read은 한 번에 요청한 모든 데이터를 반환합니다. 반환 값을 무시하고 있습니다. 그렇게하지 마십시오 ... 충분한 데이터가 있다고 가정하면, MemoryStream에 대해 괜찮을 것입니다. 또한, MemoryStream.ToArray 메서드를 사용하여 바이트 배열로 변환 할 수 있습니다.

이제 클라이언트가 문자열을 수신하는 방법을 표시하지 않았습니다. 어디에서 가져 왔습니까?

서버가 보내는 문자열과 클라이언트가받는 문자열을 기록해야합니다. 이것이 절대적인 첫 번째 단계이기 때문에 데이터가 실제로 보존되었는지 확인할 수 있습니다.

클라이언트가 빈 문자열의 압축을 푸는 중입니다 (즉, Convert.FromBase64이 빈 바이트 배열을 반환 함). 그러나 수신중인 문자열을 알기 전까지는 진행하기가 어렵습니다.

+0

안녕하세요 Jon Skeet 보낸 문자열을 기록하는 데 귀하의 조언을 시도했습니다. 클라이언트가 아무것도 수신하지 못했기 때문에 송신과 관련하여 작업해야한다고 생각합니다. 도움 주셔서 감사합니다. :) – Mark

관련 문제