gpt4 book ai didi

android - 使用 RealTimeSocket 丢失数据

转载 作者:行者123 更新时间:2023-11-29 00:29:08 26 4
gpt4 key购买 nike

我正在移植一款游戏以使用支持多人游戏的 Google Play 游戏服务。我正在使用 RealTimeSocket 而不是实时消息,因为游戏已经支持套接字。

为了获取套接字,我调用了 GamesClient.getRealTimeSocketForParticipant,然后我可以获得输入和输出流,就像将其用作普通套接字一样。

我的问题是,如果设备在调用 getRealTimeSocketForParticipant 之前接收到数据,我将无法读取该数据。例如:

Device A calls getRealTimeSocketForParticipant.Device A sends "Hello".Device B calls getRealTimeSocketForParticipant.Device B receives nothing.Device A sends "World".Device B receives "World".

I have modified one of the example projects (ButtonClicker) and replicated the problem here. I have modified the code to use realtime socket, and modified the startGame method to this:

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 秒。对于不休眠的设备,输出将类似于:

No sleep, getting socket now.Sending: 0Sending: 1Sending: 2Sending: 3Sending: 4Received data:  0Sending: 5Received data:  0 1Sending: 6Received data:  0 1 2

符合预期,没有数据丢失。但是对于其他设备,我得到了这个:

Sleeping in 5 seconds...Received data:  4Sending: 0Received data:  4 5Sending: 1Received data:  4 5 6Sending: 2Received data:  4 5 6 7Sending: 3

第一个字节丢失了。有什么办法可以避免这种情况吗?

最佳答案

如果我对 API 的理解正确,通过实时套接字交换的消息是 unrealiable ,因此您无法始终保证所有玩家都收到了您发送的所有消息。我找不到有关 RealTimeSocket 使用的网络协议(protocol)的信息,但我怀疑它是 UDP。

如果真是这样,恐怕除了实现某种 handshake 之外,您无能为力。你自己。选择一个设备(例如:具有最低 ID 的设备)作为“同步器”,并让它与所有其他设备创建一个集合。每秒发送一条消息(“SYN”),例如“你在哪里? x y z”(当然不是字面意思),直到其他人回应“我在这里!(y)”(“ACK”)。从集合中删除发送响应的设备,直到集合为空。至此,给大家送上一句“比赛开始!”继续。

请注意,这些消息中的任何都可能丢失:如果“ACK”丢失,下次发送“SYN”时,设备应再次应答。如果“游戏开始”消息丢失,运气不好,设备将一直等待,直到收到不同的消息,此时它应该认为自己可以自由开始(尽管延迟)。

最后一点:即使底层协议(protocol)是 TCP,它仍然不是 100% 可靠的,没有协议(protocol)是。参见 this question了解更多信息,如果您还不知道这一事实。

关于android - 使用 RealTimeSocket 丢失数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17136135/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com