嗨,我正在研究我的安卓游戏" Space Corsair"的实时多人游戏模块。
它基于UDP,每个设备与处理游戏逻辑的中央Java服务器通信。客户端仅发送播放器输入并从服务器对象接收位置和事件。
我的第一个POC在模拟器,nexus 7和HTC欲望上运行良好。使用相同的代码版本,我的nexus 4遇到了一些网络问题(有时它可以工作,大部分时间我遇到问题):n4似乎缓冲它们并将它们传送到我的应用程序,而不是连续读取服务器数据包批量:玩家体验的巨大问题。
第一个截图:玩游戏时的正常rx / tx图表
第二个屏幕截图:anormal rt / tx,客户端接收峰值中的所有数据
我在本地wifi网络中运行我的测试,在工作设备上ping 6毫秒,我试图增加数据包大小(现在508字节以确保一个数据包没有被清除),每隔75毫秒ping一次(而不是500 )为保持连接,我在手机设置中禁用了wifi电池优化。
奇怪的是,如果我工作正常,我会在90%的时间内上传新版本的代码。然后,当我完全退出游戏并从主屏幕再次启动时,我有滞后。我试图重新启动我的nexus 4但在启动时遇到同样的问题。
这是我的读者主题
public class UDPHandler implements Runnable {
private boolean running = false;
public static final Integer PACKET_SIZE = 508;
private final PacketRecievedListener listener;
public UDPSender sender;
public UDPHandler(PacketRecievedListener listener) {
this.listener = listener;
this.sender = new UDPSender();
}
@Override
public void run() {
running = true;
byte[] receiveData = new byte[PACKET_SIZE];
DatagramSocket serverSocket = getLocalDatagramSocket();
Logs.i("Udp with ip " + MultiUtils.getIPAddress(true) + " listening on port " + serverSocket.getLocalPort());
DatagramPacket receivePacket = new DatagramPacket(receiveData, PACKET_SIZE);
while (running) {
try {
serverSocket.receive(receivePacket);
listener.onPacketRecieved(receivePacket.getData(), receivePacket.getAddress());
receivePacket.setLength(PACKET_SIZE);
} catch (SocketException e) {
Logs.e("",e);
} catch (IOException e) {
Logs.e("",e);
}
}
}
/**
* Used to bind reader to sender socket
* Wait the sender to be ready and return the socket
* @return
*/
private DatagramSocket getLocalDatagramSocket() {
while (UDPSender.socket == null) {
try {
Logs.i("Trying to obtain socket");
Thread.sleep(500);
} catch (InterruptedException e) {
Logs.e("",e);
}
}
return UDPSender.socket;
}
public void stop() {
this.running = false;
}
}
创建套接字的代码(阅读器重用发送方套接字)
public void initSocket(){
if (socket == null){
try {
DatagramChannel channel = DatagramChannel.open();
socket = channel.socket();
socket.bind(new InetSocketAddress(UDPSender.LOCAL_LISTENER_PORT));
socket.setReuseAddress(true);
} catch (SocketException e) {
Logs.e("echec dans le socket",e);
} catch (IOException e) {
Logs.e("echec dans le socket", e);
}
}
}