我正在移植一个游戏以使用支持多人游戏的 Google Play 游戏服务。我正在使用 RealTimeSocket 而不是实时消息,因为游戏已经支持套接字。
为了获得套接字,我调用 GamesClient.getRealTimeSocketForParticipant,然后我可以获得输入和输出流,就像将它用作普通套接字一样。
我的问题是,如果设备在调用 getRealTimeSocketForParticipant 之前接收到数据,我将无法读取这些数据。例如:
设备 A 调用 getRealTimeSocketForParticipant。 设备 A 发送“Hello”。 设备 B 调用 getRealTimeSocketForParticipant。 设备 B 什么也没有收到。 设备 A 发送“世界”。 设备 B 接收“世界”。
我已经修改了一个示例项目(ButtonClicker)并在此处复制了该问题。我修改了代码以使用实时套接字,并将 startGame 方法修改为:
String mReceivedData = "";
byte mNextByteToSend = 0;
void startGame(boolean multiplayer)
{
mMultiplayer = multiplayer;
updateScoreDisplay();
switchToScreen(R.id.screen_game);
findViewById(R.id.button_click_me).setVisibility(View.VISIBLE);
GamesClient client = getGamesClient();
String myid = mActiveRoom.getParticipantId(client.getCurrentPlayerId());
ArrayList<String> ids = mActiveRoom.getParticipantIds();
String remoteId = null;
for(int i=0; i<ids.size(); i++)
{
String test = ids.get(i);
if( !test.equals(myid) )
{
remoteId = test;
break;
}
}
//One of devices should sleep in 5 seconds before start
if( myid.compareTo(remoteId) > 0 )
{
try
{
//The device that sleeps will loose the first bytes.
Log.d(TAG, "Sleeping in 5 seconds...");
Thread.sleep(5*1000);
}
catch(Exception e)
{
}
}
else
{
Log.d(TAG, "No sleep, getting socket now.");
}
try
{
final RealTimeSocket rts = client.getRealTimeSocketForParticipant(mRoomId, remoteId);
final InputStream inStream = rts.getInputStream();
final OutputStream outStream = rts.getOutputStream();
final TextView textView =((TextView) findViewById(R.id.score0));
//Thread.sleep(5*1000); Having a sleep here instead minimizes the risk to get the problem.
final Handler h = new Handler();
h.postDelayed(new Runnable()
{
@Override
public void run()
{
try
{
int byteToRead = inStream.available();
for(int i=0; i<byteToRead; i++)
{
mReceivedData += " " + inStream.read();
}
if( byteToRead > 0 )
{
Log.d(TAG, "Received data: " + mReceivedData);
textView.setText(mReceivedData);
}
Log.d(TAG, "Sending: " + mNextByteToSend);
outStream.write(mNextByteToSend);
mNextByteToSend++;
h.postDelayed(this, 1000);
}
catch(Exception e)
{
}
}
}, 1000);
}
catch(Exception e)
{
Log.e(TAG, "Some error: " + e.getMessage(), e);
}
}
该代码确保两个设备之一在调用 getRealTimeSocketForParticipant 之前休眠 5 秒。对于不休眠的设备,输出将类似于:
不睡觉,现在正在获取插座。 发送:0 发送:1 发送:2 发送:3 发送:4 接收数据:0 发送:5 接收数据:0 1 发送:6 接收数据:0 1 2
这是预期的,没有数据丢失。但是对于其他设备,我得到了这个:
睡5秒... 接收数据:4 发送:0 接收数据:4 5 发送:1 接收数据:4 5 6 发送:2 接收数据:4 5 6 7 发送:3
第一个字节丢失。有没有办法避免这种情况?