2014-12-10 3 views
1

Я использую Games.RealTimeMultiplayer.sendReliableMessage для отправки сообщений на Android, но они, похоже, выходят из строя. В 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(); 
    } 

Что это делает сначала отправить сообщение с размером пакета в, затем разделить пакет вверх, если необходимо, и отправить его. Выход журнала выглядит следующим образом:

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-байтовый размер пакета, а затем повторно собирает пакет как сообщения приходят, выглядит следующим образом:

@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(); 
    } 
} 

Но вход в систему принимающая сторона выглядит следующим образом:

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 

Как вы можете видеть, ближе к концу, пакеты приходят из строя. У кого-нибудь еще были проблемы с этим в режиме реального времени на Android?

ответ

0

Вы решили эту проблему? Похоже, что реализация не гарантирует порядок. Итак, что вы можете сделать, это проверить результат обратного вызова (onRealTimeMessageSent) для этого идентификатора сообщения (называемый токеном и перенастроенный на sendReliableMessage), и только когда результат в порядке, отправьте следующий пакет.

+1

Я закончил тем, что менял структуру пакета, чтобы содержать идентификатор в заголовке, который увеличивается с каждым пакетом, чтобы получатель мог отслеживать порядок пакетов и изменять порядок заказов, которые выходят из строя. Это немного быстрее, чем ждать подтверждения каждого пакета. Я думаю, вы правы, что есть ошибка в реализации, или документация неверна. –

+0

Эта проблема возникла у меня, и после некоторых тестов я пришел к выводу, что 'sendReliableMessage' не гарантирует, что пакеты будут доставлены в том же порядке. Я просто решил дождаться обратного вызова 'onRealTimeMessageSent' для обеспечения порядка на стороне отправителя. – nradk

Смежные вопросы