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
마지막 부분에서 알 수 있듯이 패킷의 순서가 잘못되었습니다. 안드로이드에서 실시간 멀티 플레이와 함께 이런 문제가 생긴 사람이 있습니까?
각 패킷마다 증가하는 헤더에 ID를 포함하도록 패킷 구조를 변경했기 때문에 수신자는 패킷의 순서를 추적하고 순서가 잘못된 패킷의 순서를 바꿀 수 있습니다. 각 패킷의 확인을 기다리는 것보다 약간 빠릅니다. 구현에 버그가 있거나 문서가 올바르지 않다고 생각합니다. –
동일한 문제가 나에게 발생했고, 일부 테스트 후에'sendReliableMessage'가 패킷이 동일한 순서로 전달된다는 것을 보증하지 않는다고 결론을 내렸다. 방금 보낸 쪽에서 주문을 시행하기 위해'onRealTimeMessageSent' 콜백을 기다리기로 결정했습니다. – nradk