Я использую 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?
Я закончил тем, что менял структуру пакета, чтобы содержать идентификатор в заголовке, который увеличивается с каждым пакетом, чтобы получатель мог отслеживать порядок пакетов и изменять порядок заказов, которые выходят из строя. Это немного быстрее, чем ждать подтверждения каждого пакета. Я думаю, вы правы, что есть ошибка в реализации, или документация неверна. –
Эта проблема возникла у меня, и после некоторых тестов я пришел к выводу, что 'sendReliableMessage' не гарантирует, что пакеты будут доставлены в том же порядке. Я просто решил дождаться обратного вызова 'onRealTimeMessageSent' для обеспечения порядка на стороне отправителя. – nradk