2010-04-23 4 views
2

Silverlight Multiplayer Chess 게임 개발을 중단 한 지 4 개월이 지났습니다.Silverlight 소켓 및 메시지 전달에 대한 도움말

alt text http://img408.imageshack.us/img408/8355/chess.gif

문제는 내가 재현 할 수 버그 느릅 나무이었다. 이 테스트가 있었기 때문에 매우 슬 am습니다. Silverlight 멀티 플레이어 게임이 성공하면이 게임이 올 것입니다. 인터넷에 프로그래밍을하는 동안 소켓을 사용하는 사람은 적지 만, 그런 식으로하는 방법에 대한 예는 없습니다. 나는 이번 주에 약간의 자유 시간을 가지고 있기 때문에

나는 문제를 발견하고 관리하고 지금은 버그를 재현 할 수 있어요.

내가 바로 아래의 예처럼 그들 사이의 지연없이 클라이언트에서 10 개의 메시지, 다른 후 하나를 보낼 경우

// when I press Enter, the client will 10 messages with no delay between them 
private void textBox_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Enter && textBox.Text.Length > 0) 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      MessageBuilder mb = new MessageBuilder(); 
      mb.Writer.Write((byte)GameCommands.NewChatMessageInTable); 
      mb.Writer.Write(string.Format("{0}{2}: {1}", ClientVars.PlayerNickname, textBox.Text, i)); 
      SendChatMessageEvent(mb.GetMessage()); 

      //System.Threading.Thread.Sleep(100); 
     } 

     textBox.Text = string.Empty; 
    } 
} 

    // the method used by client to send a message to server 
    public void SendData(Message message) 
    { 
     if (socket.Connected) 
     { 
      SocketAsyncEventArgs myMsg = new SocketAsyncEventArgs(); 
      myMsg.RemoteEndPoint = socket.RemoteEndPoint; 
      byte[] buffer = message.Buffer; 
      myMsg.SetBuffer(buffer, 0, buffer.Length); 

      socket.SendAsync(myMsg); 
     } 
     else 
     { 
      string err = "Server does not respond. You are disconnected."; 
      socket.Close(); 
      uiContext.Post(this.uiClient.ProcessOnErrorData, err); 
     } 
    } 

    // the method used by server to receive data from client 
    private void OnDataReceived(IAsyncResult async) 
    { 
     ClientSocketPacket client = async.AsyncState as ClientSocketPacket; 
     int count = 0; 
     try 
     { 
      if (client.Socket.Connected) 
       count = client.Socket.EndReceive(async); 
      // THE PROBLEM IS HERE 
      // IF SERVER WAS RECEIVE ALL MESSAGES SEPARATELY, ONE BY ONE, THE COUNT 
      // WAS ALWAYS 15, BUT BECAUSE THE SERVER RECEIVE 3 MESSAGES IN 1, THE COUNT 
      // IS SOMETIME 45 
     } 
     catch 
     { 
      HandleException(client); 
     } 

     client.MessageStream.Write(client.Buffer, 0, count); 

     Message message; 

     while (client.MessageStream.Read(out message)) 
     { 
      message.Tag = client; 
      ThreadPool.QueueUserWorkItem(new WaitCallback(this.processingThreadEvent.ServerGotData), message); 
      totalReceivedBytes += message.Buffer.Length; 
     } 

     try 
     { 
      if (client.Socket.Connected) 
       client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, 0, new AsyncCallback(OnDataReceived), client); 
     } 
     catch 
     { 
      HandleException(client); 
     } 
    } 

만 3 큰 메시지 및 모든 큰 메시지가 전송되는 것 같다 3 개 또는 4 개의 작은 메시지가 포함됩니다. 이것은 내가 원하는 행동이 아닙니다. 내가 메시지 전달 사이에 100 밀리 초 지연을 넣으면

은 모든 것이 잘 동작이지만, 현실 세계에서 시나리오 사용자들은 그들 사이에 1 밀리 초에서 서버로 메시지를 보낼 수 있습니다.

  1. 는 모든 설정은 나는 그들이 전체 메시지 내가 해달라고 (모든 시간이며, 1에서 3 메시지를받을 경우에도
  2. 이 클라이언트가 한 번에 하나의 메시지를 보낼 수 있도록하기 위해 수행, 또는 수 있는가 하나의 커다란 메시지로 2.5 메시지를 받고 싶지 않습니다)? 만약 그들이 그렇다면, 나는 그들을 읽고이 새로운 상황을 대할 수 있습니다.

답변

2

당신은 TCP의 주요 기능을 놓쳤습니다. 이것은 메시지 기반 프로토콜이 아니기 때문입니다. 모든 데이터를 단일 "파이프"로 보냅니다. 파이프에 5 컵의 물을 넣으면 5 컵이 아니라 다른 끝에 물통이 생깁니다. 버킷에서 물을 꺼내기에 충분히 빠른 경우 5 컵 또는 10 개의 반컵 또는 1 개의 버킷을 얻을 수 있습니다. TCP와 동일합니다. 메시지가 필요한 경우 각 메시지의 시작과 끝에 마커를 넣고 수신 측에서 스트림을 구문 분석해야합니다.

관련 문제