2012-08-31 2 views
0

메신저잘못된 paramether (MemoryStream을)은

이는 같이 sendData 및 GetData의 기능 과 Image.FromStream 기능을 사용할 때 항상 잘못된 매개 변수를 얻을 수있다 네트워크 스트림을 통해 이미지를 보내려고, 내가 한 내 코드 : 화면에서 그림을 가져온 다음 byte []로 변환합니다. networkStream을 통해 전송하는 메모리 스트림에 삽입합니다. 문제의

private void SendData() 
    { 
     StreamWriter swWriter = new StreamWriter(this._nsClient); 
     // BinaryFormatter bfFormater = new BinaryFormatter(); 

     // this method 
     lock (this._secLocker) 
     { 
      while (this._bShareScreen) 
      { 
       // Check if you need to send the screen 
       if (this._bShareScreen) 
       { 
        MemoryStream msStream = new MemoryStream(); 
        this._imgScreenSend = new Bitmap(this._imgScreenSend.Width, this._imgScreenSend.Height); 
        // Send an image code 
        swWriter.WriteLine(General.IMAGE); 
        swWriter.Flush(); 

        // Copy image from screen 
        this._grGraphics.CopyFromScreen(0, 0, 0, 0, this._sizScreenSize); 
        this._imgScreenSend.Save(msStream, System.Drawing.Imaging.ImageFormat.Jpeg); 
        msStream.Seek(0, SeekOrigin.Begin); 

        // Create the pakage 
        byte[] btPackage = msStream.ToArray(); 

        // Send its langth 
        swWriter.WriteLine(btPackage.Length.ToString()); 
        swWriter.Flush(); 

        // Send the package 
        _nsClient.Write(btPackage, 0, btPackage.Length); 
        _nsClient.Flush(); 
       } 
      } 
     } 
    } 


    private void ReciveData() 
    { 
     StreamReader srReader = new StreamReader(this._nsClient); 
     string strMsgCode = String.Empty; 
     bool bContinue = true; 
     //BinaryFormatter bfFormater = new BinaryFormatter(); 
     DataContractSerializer x = new DataContractSerializer(typeof(Image)); 
     // Lock this method 
     lock (this._objLocker) 
     { 
      while (bContinue) 
      { 
       // Get the next msg 
       strMsgCode = srReader.ReadLine(); 

       // Check code 
       switch (strMsgCode) 
       { 
        case (General.IMAGE): 
         { 
          // Read bytearray 
          int nSize = int.Parse(srReader.ReadLine().ToString()); 
          byte[] btImageStream = new byte[nSize]; 
          this._nsClient.Read(btImageStream, 0, nSize); 

          // Get the Stream 
          MemoryStream msImageStream = new MemoryStream(btImageStream, 0, btImageStream.Length); 

          // Set seek, so we read the image from the begining of the stream 
          msImageStream.Position = 0; 

          // Build the image from the stream 
          this._imgScreenImg = Image.FromStream(msImageStream); // Error Here 

답변

1

부분은 쓰기의 끝에서 Environment.NewLine 추가를 WriteLine()를 사용하고 있다는 점이다. 다른 쪽 끝에서 Read()를 호출하면 해당 개행을 제대로 처리하지 못합니다.

스트림에 Write()를 수행 한 다음 다른 끝에서 다시 읽는 것입니다.

문자열로의 변환이 이상합니다.

이미지를 전송할 때 수행중인 작업은 바이트 배열을 전송 중입니다. 필요한 스트림의 길이를 보낸 다음 이미지 자체를 보낸 다음 상대방의 길이와 바이트 배열을 읽는 것뿐입니다.

와이어를 통해 바이트 배열을 전송하는 가장 기본적이고 간단한 방법은 먼저 배열의 길이를 나타내는 정수를 보내고받는 사람의 길이를 읽는 것입니다.

얼마나 많은 양의 데이터를주고 받았는지 알게되면, 배열을 와이어의 바이트 배열로 보내고 이전에 다른 쪽에서 결정한 길이를 읽습니다.

이제 원시 바이트와 크기가 있으므로 버퍼에서 올바른 이미지 객체 (또는 방금 보낸 다른 이진 형식)로 배열을 재구성 할 수 있습니다.

또한 DataContractSerializer가 왜 있는지 잘 모르겠습니다. 원시 이진 데이터이고, 이미 수동으로 바이트로 직렬화하고 있으므로 유용하지 않습니다.

소켓 및 스트림을 사용하는 네트워크 프로그래밍의 근본적인 문제 중 하나는 프로토콜을 정의하는 것입니다. 왜냐하면 수신 측에서는 무엇을 기대해야하는지 또는 스트림이 끝나는지를 알 수 없기 때문입니다. 그래서 공통 프로토콜은 매우 엄격하게 정의 된 패킷 크기와 레이아웃을 가지고 있거나 수신자가 무엇을 해야할지 알 수 있도록 길이/데이터 쌍을 보내는 것과 같은 기능을합니다.

배열 길이를 나타내는 정수를 보내고받는 쪽에서 정수를 읽는 것과 같은 매우 간단한 프로토콜을 구현하는 경우 절반의 목표를 달성했습니다. 그런 다음 발신자와 수신자 모두 다음에 발생할 일에 대해 동의합니다. 그런 다음 송신자는 와이어에서 정확히 해당 바이트 수를 전송하고 수신자는 와이어의 해당 바이트 수를 정확히 읽고 읽기가 완료된 것으로 간주합니다. 지금 가지고있는 것은 원래의 바이트 배열을 수신 측에 정확히 복사 한 것입니다. 그리고 그 데이터가 처음부터 무엇인지 알았으므로, 원하는대로 그것을 할 수 있습니다.

코드 예가 ​​필요한 경우 간단한 예제를 제공하거나 그물에서 사용할 수있는 예제가 많이 있습니다.

+0

나는 기록 라인에 내의 readLine의 독서를 보낸다위한 최선의 코드가 아닙니다

int byteCount=0; while(byteCount < nSize) { int read = this._nsClient.Read(btImageStream, byteCount, nSize-byteCount); byteCount += read; } 

내가 ReciveData 있도록 메시지 "IMG"를 보내고 becuse이있다 함수는 이제 이미지를 암송하게 될 것이며, 배열의 크기를 쓰기 라인에 보내고 readline에서 읽습니다. 배열에서 문자를 보내고 읽기와 함께 읽습니다. 요점을 이해하지 못합니다. –

1

짧게 유지하려고 시도 : (사용하는) Stream.Read 함수는 읽은 바이트 수를 나타내는 int를 반환합니다. 이것은 반환되어 필요한 모든 바이트가 수신되었는지 확인할 수 있습니다. 무엇인가 :이 작업

+0

이게 도움이 될 것 같아서 고맙지 만 지금은 더 가벼운 problom을 가지고 있습니다. write 메소드가 모든 데이터를 보내지는 않습니다. 어떻게 해결할 수 있습니까? –

+0

죄송합니다. 왜 쓰기가 전체 데이터를 보내지 않는지 이유를 생각할 수 없습니다. MSDN에 따르면 네트워크 스트림에서 flush()를 호출하는 용도는 없습니다. –