2013-01-24 6 views
0

좋아, 내 게임을 위해서 필자는 서버/클라이언트 피어 투 피어 (peer to peer) 연결을 설정하고 위치 등을 앞뒤로 보냈다.비동기 TCP 서버/클라이언트 신뢰할 수없는 패킷?

비록 내 메시지가 실제로는 빠르지 만 안정적이지는 않지만. 여기

public void RecieveAsync() 
    { 

     if (netStream == null) netStream = Server.GetStream(); 


     if (netStream.DataAvailable == false) return; 

     netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, new AsyncCallback(recieveCallBack), netStream); 




    } 


    public void recieveCallBack(IAsyncResult ar) 
    { 
     //try 
     //{ 

     String content = String.Empty; 

     Console.WriteLine("Stuck trying to get data"); 

     int rec = netStream.EndRead(ar); 



     if (rec > 0) 
     { 


       Console.WriteLine(Encoding.ASCII.GetString(
    ReadBuffer, 0, rec)); 

      string packet = Encoding.ASCII.GetString(
    ReadBuffer, 0, rec); 
       bool completedPacket = false; 
       int appendTo = rec; 

       if (packet.Contains("<eof>")) 
       { 
        appendTo = packet.IndexOf("<eof>"); 
        packet.Replace("<eof>", ""); 
        completedPacket = true; 
       } 

       SB.Append(packet, 0, appendTo); 

       // Check for end-of-file tag. If it is not there, read 
       // more data. 

       content = SB.ToString(); 



      if (completedPacket) 
      { 
       // All the data has been read from the 
       // client. Display it on the console. 


       if (DataRecieved != null) 
       { 
        string RecievedData = SB.ToString(); 

        DataRecieved(RecievedData); 

        netStream.Flush(); 

        Array.Clear(ReadBuffer, 0, ReadBuffer.Length); 
        ReadBuffer = new byte[1024]; 
       } 

       SB.Clear(); 

       // Echo the data back to the client. 
      } 
      else 
      { 
       // Not all data received. Get more. 
       Array.Clear(ReadBuffer, 0, ReadBuffer.Length); 
       ReadBuffer = new byte[1024]; 
       netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream); 
      } 


     } 

    } 

그리고 내 보내는 코드 :

을 .T 어쨌든 내 잡 코드가 여기에 문자열의 일부와 같이 (왜 확실하지)없는, 때로는 전송은 중지하고 스레드 나던 계속된다 :

public void Send(byte[] data, int index, int length) 
    { 
     //add data as state 

     //socket.NoDelay = true; 

     if (netStream == null) netStream = TcpClient.GetStream(); 

     netStream.BeginWrite(data, 0, length, sendCallback, netStream); 




    } 

    private void sendCallback(IAsyncResult ar) 
    { 
     //try 
     //{ 
      netStream.EndWrite(ar); 

      //if (ar.AsyncState != null) 
      //{ 
      // byte[] buffer = (byte[])ar.AsyncState; 
      // socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, sendCallback, null); 
      // return; 
      //} 

      if (OnSend != null) 
      { 
       OnSend(this); 
      } 

      netStream.Flush(); 


     //catch (Exception ex) 
     //{ 
     // System.Windows.Forms.MessageBox.Show(ex.ToString()); 
     // return; 
     //} 
    } 

패킷은 Encoding.ASCII.Getbytes에 있습니다.

그리고 서버와 클라이언트가 while (true) 스레드에서 Thread.Sleep (1)로 업데이트 중입니다.

+0

도 패킷 끝을 표시합니다. – user1965626

+0

이 읽기간에 분할된다고 가정하십시오. – spender

+0

또한 전송 된 패킷을 병합하고 프레이밍 ('')을 제거합니다. 'DataReceived'는 하나의 "패킷"(기본 네트워크 용어가 아닌 용어로) 이상을 제공 할 수 있으며이를 해독 할 방법이 없습니다. 근본적으로 여기서해야 할 일은받는 모든 것을 기록하고 처리하는 모든 것을 기록하는 것입니다. 그러면 어떤 일이 잘못되는지 알 수 있습니다. –

답변

0

비트 단위로 문자열을 재구성하려고하기 때문에 (이 방법은 UTF8과 같은보다 일반적인 멀티 바이트 인코딩을 사용하면 손상 될 수 있음)이 방법은 취약합니다.

제 의견에 언급했듯이 <eof>은 두 번 읽는 것으로 나누어 져 있기 때문에 놓칠 수 있습니다.

IMO를 사용하는 것이 좋습니다. 메시지 끝 부분에 아무 것도 끝내지 않아도 메시지를 끝내야 할 필요가 없도록 메시지 앞에 선행 길이 필드 (4 바이트 정수)를 추가하는 것이 좋습니다.

표시되는 메시지 길이에 도달 할 때까지 모든 읽기를 MemoryStream에 부어 넣은 다음 적합하다고 보이는 인코딩으로 MemoryStream의 내용을 디코딩하십시오.

+0

내 메시지에 태그를다는 것은 무엇을 의미합니까? 길이를 표시하기 전에 패킷을 보내는 것처럼? – user1965626

+0

@ user1965626 : 네, 정확히는 ... 길이를 나타내는 4 바이트의 "패킷"입니다. 따라서 읽기는 다음과 같이 구성됩니다. 1. 길이를 나타내는 몇 바이트를 읽습니다 (int 인 경우 4 일 것입니다). 2. length '메시지를 얻기위한 바이트 – spender