2014-12-10 2 views
1

Android에서 메시지를 보내려면 Games.RealTimeMultiplayer.sendReliableMessage를 사용하고 있지만 순서가 잘못된 것 같습니다. concept document 상태 :RealTimeMultiplayer.sendReliableMessage 메시지가 순서대로 수신되었습니다.

신뢰할 수있는 메시징. 안정적인 메시징을 통해 데이터 전달, 무결성 및 주문이 보장됩니다.

큰 패킷을 여러 개의 1400 바이트 메시지로 분할하고 각 패킷을 sendReliableMessage로 루프로 보내고 있습니다. 이 루프가 끝나면 sendReliableMessage를 사용하여 다른 메시지를 보내지 만 수신 장치에서는 마지막 메시지가 다른 메시지보다 먼저 전달됩니다. 패킷을 전송하는 코드는 다음과 같습니다.

public void sendPacket(Packet packet) 
{ 
    try { 

     Log.d(getPackageName(), "Sending packet: " + packet.getClass().getSimpleName()); 

     ByteArrayOutputStream byteOutpuStream = new ByteArrayOutputStream(); 
     ObjectOutputStream outputStream = new ObjectOutputStream(byteOutpuStream); 
     outputStream.writeObject(packet); 
     byte[] bytes = byteOutpuStream.toByteArray(); 
     outputStream.close(); 

     if(m_Participants != null) { 
      for (Participant participant : m_Participants) { 
       if (participant.getParticipantId().equals(m_LocalParticipantID) == false) { 

        Log.d(getPackageName(), "Sending object size " + bytes.length + " to participant " + participant.getParticipantId()); 
        byte[] objectSize = ByteBuffer.allocate(4).putInt(bytes.length).array(); 
        int sendResult = Games.RealTimeMultiplayer.sendReliableMessage(m_GoogleClient, this, objectSize, m_RoomID, participant.getParticipantId()); 
        Log.d(getPackageName(), "Send object size result: " + sendResult); 

        Log.d(getPackageName(), "Sending packet to " + participant.getParticipantId()); 
        int bytesRemaining = bytes.length; 
        if(bytesRemaining <= Multiplayer.MAX_RELIABLE_MESSAGE_LEN) 
        { 
         Log.d(getPackageName(), "Sending full packet " + bytesRemaining + " bytes"); 
         sendResult = Games.RealTimeMultiplayer.sendReliableMessage(m_GoogleClient, this, bytes, m_RoomID, participant.getParticipantId()); 
         Log.d(getPackageName(), "Send packet result: " + sendResult); 
        } 
        else 
        { 
         int sentAmount = 0; 
         byte[] bufferToSend = new byte[Multiplayer.MAX_RELIABLE_MESSAGE_LEN]; 
         while(bytesRemaining > 0) { 
          int byteCountSent = 0; 
          if(bytesRemaining >= Multiplayer.MAX_RELIABLE_MESSAGE_LEN) 
          { 
           byteCountSent = Multiplayer.MAX_RELIABLE_MESSAGE_LEN; 
           for(int byteIndex = 0; byteIndex < byteCountSent; ++byteIndex) 
           { 
            bufferToSend[byteIndex] = bytes[sentAmount + byteIndex]; 
           } 
          } 
          else 
          { 
           byteCountSent = bytesRemaining; 
           bufferToSend = Arrays.copyOfRange(bytes, sentAmount, sentAmount + bytesRemaining); 
          } 
          Log.d(getPackageName(), "Sending " + bufferToSend.length + " bytes"); 
          sendResult = Games.RealTimeMultiplayer.sendReliableMessage(m_GoogleClient, this, bufferToSend, m_RoomID, participant.getParticipantId()); 
          Log.d(getPackageName(), "Send packet result: " + sendResult); 

          bytesRemaining -= byteCountSent; 
          sentAmount += byteCountSent; 
         } 
        } 
       } 
      } 
     } 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

패킷 크기가 포함 된 메시지를 보낸 다음 필요한 경우 패킷을 분할하여 보냅니다. 에

@Override 
public void onRealTimeMessageReceived(RealTimeMessage realTimeMessage) 
{ 
    try { 

     byte[] data = realTimeMessage.getMessageData(); 
     Log.d(getPackageName(), "onRealTimeMessageReceived: " + data.length + " bytes"); 

     // Are we expecting a packet? 
     if(m_CurrentPacketData == null) 
     { 
      // Get the packet size 
      if(data.length != 4) 
      { 
       Log.d(getPackageName(), "Error! 4 bytes expected for packet size, got " + data.length); 
      } 
      else 
      { 
       int packetSize = ByteBuffer.wrap(data).getInt(); 
       m_CurrentPacketData = new byte[packetSize]; 
       m_CurrentPacketReceiveCount = 0; 
      } 
     } 
     else 
     { 
      // Append the data to the packet 
      Log.d(getPackageName(), "Received data of " + data.length + " bytes"); 
      for(int byteIndex = 0; byteIndex < data.length; ++byteIndex) 
      { 
       m_CurrentPacketData[m_CurrentPacketReceiveCount + byteIndex] = data[byteIndex]; 
      } 
      m_CurrentPacketReceiveCount += data.length; 

      // Have we received it all? 
      if(m_CurrentPacketReceiveCount == m_CurrentPacketData.length) 
      { 
       Log.d(getPackageName(), "Full packet received"); 

       ByteArrayInputStream byteInputStream = new ByteArrayInputStream(m_CurrentPacketData); 
       ObjectInputStream inputStream = new ObjectInputStream(byteInputStream); 
       Packet packet = (Packet) inputStream.readObject(); 
       inputStream.close(); 
       m_ReceivedPackets.add(packet); 

       Log.d(getPackageName(), "Packet received: " + packet.getClass().getSimpleName()); 

       m_CurrentPacketData = null; 
       m_CurrentPacketReceiveCount = 0; 

       processReceivedPackets(); 
      } 
      else 
      { 
       Log.d(getPackageName(), "Still " + (m_CurrentPacketData.length - m_CurrentPacketReceiveCount) + " bytes remaining"); 
      } 
     } 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

그러나 로그 :처럼 보이는

First call to sendPacket: 

Sending object size 62234 to participant p_CImSt4aNy73IiQEQAQ 
Send object size result: 1 

Sending packet to p_CImSt4aNy73IiQEQAQ 
Sending 1400 bytes 
Send packet result: 2 
Sending 1400 bytes 
Send packet result: 3 
Sending 1400 bytes 
... 
Send packet result: 44 
Sending 1400 bytes 
Send packet result: 45 
Sending 634 bytes 
Send packet result: 46 

Next call to sendPacket: 

Sending packet: StartGamePacket 
Sending object size 267 to participant p_CImSt4aNy73IiQEQAQ 
Send object size result: 47 

Sending packet to p_CImSt4aNy73IiQEQAQ 
Sending full packet 267 bytes 
Send packet result: 48 

수신 기능은 4 바이트 패킷 크기를 가져옵니다 다음 메시지가 와서으로 패킷을 재 조립하는 것입니다 : 로그 출력은 같다 수신 끝은 다음과 같습니다.

onRealTimeMessageReceived: 4 bytes 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 60834 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 59434 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 58034 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 56634 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 55234 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 53834 bytes remaining 
... 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 17434 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 16034 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 14634 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 13234 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 11834 bytes remaining 
onRealTimeMessageReceived: 634 bytes 
Received data of 634 bytes 
Still 11200 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 9800 bytes remaining 
onRealTimeMessageReceived: 4 bytes 
Received data of 4 bytes 
Still 9796 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 8396 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 6996 bytes remaining 
onRealTimeMessageReceived: 267 bytes 
Received data of 267 bytes 
Still 6729 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 5329 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 3929 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 2529 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 
Still 1129 bytes remaining 
onRealTimeMessageReceived: 1400 bytes 
Received data of 1400 bytes 

마지막 부분에서 알 수 있듯이 패킷의 순서가 잘못되었습니다. 안드로이드에서 실시간 멀티 플레이와 함께 이런 문제가 생긴 사람이 있습니까?

답변

0

이 문제가 해결 되었습니까? 구현이 주문을 보장하지 않는 것 같습니다. 따라서 수행 할 작업은이 메시지 ID (토큰이라고하고 sendReliableMessage에 의해 다시 호출 됨)에 대한 콜백 결과 (onRealTimeMessageSent)를 확인하고 결과가 OK 인 경우에만 다음 패킷을 보냅니다.

+1

각 패킷마다 증가하는 헤더에 ID를 포함하도록 패킷 구조를 변경했기 때문에 수신자는 패킷의 순서를 추적하고 순서가 잘못된 패킷의 순서를 바꿀 수 있습니다. 각 패킷의 확인을 기다리는 것보다 약간 빠릅니다. 구현에 버그가 있거나 문서가 올바르지 않다고 생각합니다. –

+0

동일한 문제가 나에게 발생했고, 일부 테스트 후에'sendReliableMessage'가 패킷이 동일한 순서로 전달된다는 것을 보증하지 않는다고 결론을 내렸다. 방금 보낸 쪽에서 주문을 시행하기 위해'onRealTimeMessageSent' 콜백을 기다리기로 결정했습니다. – nradk

관련 문제