Android实时多人游戏UDP延迟wifi

时间:2014-05-20 08:18:49

标签: java android networking udp lag

问题介绍

嗨,我正在研究我的安卓游戏" Space Corsair"的实时多人游戏模块。

它基于UDP,每个设备与处理游戏逻辑的中央Java服务器通信。客户端仅发送播放器输入并从服务器对象接收位置和事件。

我的第一个POC在模拟器,nexus 7和HTC欲望上运行良好。使用相同的代码版本,我的nexus 4遇到了一些网络问题(有时它可以工作,大部分时间我遇到问题):n4似乎缓冲它们并将它们传送到我的应用程序,而不是连续读取服务器数据包批量:玩家体验的巨大问题。

网络图

第一个截图:玩游戏时的正常rx / tx图表

normal rt/tx

第二个屏幕截图:anormal rt / tx,客户端接收峰值中的所有数据

problematic 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);
        }
    }

}

0 个答案:

没有答案