joc*_*lyn 5 java networking android udp lag
大家好,我正在开发我的 Android 游戏“Space Corsair”的实时多人游戏模块。
它基于 UDP,每个设备都与处理游戏逻辑的中央 Java 服务器进行通信。客户端仅发送玩家输入并从服务器接收对象位置和事件。
我的第一个 POC 在模拟器、Nexus 7 和 HTC Desire 上运行良好。使用相同的代码版本,我的 Nexus 4 遇到一些网络问题(有时它可以工作,但大多数时候我都遇到问题):n4 似乎不是连续读取服务器数据包,而是缓冲它们并将它们传递到我的应用程序批量:玩家体验的巨大问题。
第一张截图:玩游戏时的正常 rx/tx 图

第二张截图:异常 rt/tx,客户端在峰值中接收到所有数据

我在工作设备上使用 6 毫秒 ping 的本地 wifi 网络运行测试,我尝试增加数据包大小(现在为 508 字节,以确保一个数据包不会被丢弃),每 75 毫秒(而不是 500)执行一次 ping 操作以保持连接起来后,我在手机设置中禁用了 WiFi 电池优化。
奇怪的是,当我通过 USB 上传新版本的代码时,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;
}
}
Run Code Online (Sandbox Code Playgroud)
以及创建套接字的代码(读者重用发送者套接字)
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
775 次 |
| 最近记录: |