2014-12-10 46 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)是否为此消息ID(称为令牌并由sendReliableMessage重新调用),并且只有当结果为OK时才发送下一个数据包。

+1

我最终改变了数据包结构以在头中包含一个随每个数据包递增的ID,这样接收者就可以跟踪数据包的顺序并重新排列顺序到达的顺序。这比等待每个数据包的确认要快一点。我认为你是对的,在实现中有一个错误,或者文档不正确。 – 2015-06-15 15:45:34

+0

同样的问题发生在我身上,经过一些测试后,我断定'sendReliableMessage'不能保证数据包将以相同的顺序传递。我只是决定等待'onRealTimeMessageSent'回调来强制发送方的排序。 – nradk 2017-02-21 08:46:54