编程语言
首页 > 编程语言> > Java Socket Server滞后于两个客户端

Java Socket Server滞后于两个客户端

作者:互联网

我是StackOverflow的新手lol,但我一直依赖这个网站.我有一个关于我创建的Java套接字服务器的问题.在连接(客户端和服务器)时,我的应用程序为该客户端创建一个线程.这是一款MMORPG游戏服务器……至少是尝试过.有一个玩家,它不会落后那么糟糕.然而,有两个,它开始显示一些滞后…

如果我在其中一个客户端上左右 – 左右 – 发送垃圾邮件,并且正常地与另一个客户端一起移动,则另一个会感到毛病.我希望得到一些助手,因为我已经花了一个半星期的时间来纠结=)这是我寻求帮助的时候了.

代码很简单:

public static void main(String[] args) throws IOException{
    serverRooms.put(roomNumber, new Room());

    try {
        System.out.println("Starting Server...");
        serverSocket = new ServerSocket(9595, 20);

        System.out.println("Server Started");
        while(run){
            Socket socket = serverSocket.accept();      // Check if we have a connection, otherwise wait

            Player player = new Player(playerCount++, socket, roomNumber);
            new Thread(player).start();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

这就是全部开始的方式!在Player对象上,它看起来像:

public void run() {
    while(playerIsConnected) {
        try {
            int msgid = input.readUnsignedByte();
            messageHandler(this, msgid);

        } catch (IOException e) {
            System.err.println("Player have signed off");
            playerIsConnected = false;
        }
    }

    // If Player leaves, close socket, and end thread
    try {
        socket.close();
    } catch (IOException e) {
        System.out.println("We got an error while closing a socket on player " + pid + ".");
    }
}

messageHandler碰巧是Final Static类的静态方法.它是一个可以被每个线程调用的全局方法(这可能是滞后的原因吗?)

public final class MessageControl {

public static void messageHandler(Player player, int msgid) throws IOException{
    DataInputStream input = player.getInputStream();
    switch (msgid) {
        case 10:
            byte hspd = (byte) Math.signum(input.readByte());
            byte vspd = (byte) Math.signum(input.readByte());
            byte dir = input.readByte();

            updatePlayerPosition(player);
            byte spd = (byte) (hspd != 0 && vspd != 0 ? player.spd-1 : player.spd);

            // Prepare packet and send to clients
            ByteBuffer buffer = ByteBuffer.allocate(11);
            buffer.put((byte) 10);
            buffer.put(shortToByte_U16(player.pid));
            buffer.put(shortToByte_U16(player.x));
            buffer.put(shortToByte_U16(player.y));
            buffer.put((byte)(hspd*spd));
            buffer.put((byte)(vspd*spd));
            buffer.put((byte)(dir));
            sendPacketToAllClients(player, buffer, true);

            // Update Player info
            player.hspd = (byte) hspd;
            player.vspd = (byte) vspd;
            player.dir = dir;
            player.lastUpdate = System.currentTimeMillis();
        break;
    }
private static void sendPacketToAllClients(Player player, ByteBuffer buffer, boolean includeMe){
    for (Player otherPlayer : player.room.getPlayersInRoom()){
        if (otherPlayer.pid != player.pid || includeMe){
            sendPacketToClient(otherPlayer, buffer);
        }
    }
}
}

关于shortToByte_U16(),我刚刚创建了一个简单的方法,将锥形短路到字节(通过字节向客户端发送缓冲包).例如,我有大约5个这样的转换,其中包括转换为无符号u16

public static byte[] shortToByte_16(int x){
    short s = (short) x;
    byte[] ret = new byte[2];
    ret[0] = (byte)(s & 0xff);
    ret[1] = (byte)((s >> 8) & 0xff);
    return ret;
}

看看下面的结构,为什么我会落后的任何想法?

编辑:我认为我通过将setTcpNoDelay设置为true来改进它.当我在我的结尾处左/右发垃圾时,似乎仍然存在滞后……我屏幕上的其他玩家似乎很不舒服.

            Socket socket = serverSocket.accept();      // Check if we have a connection, otherwise wait
            socket.setTcpNoDelay(true);  // This helped a lot!!!
            Player player = new Player(playerCount++, socket, roomNumber);
            new Thread(player).start();

从我所看到的……我的“垃圾邮件左/右”结束似乎缺少服务器发送的数据包.

解决方法:

问题解决了. =)setTcpNoDelay true做了伎俩.关于我说我丢失数据包的部分,我实际上没有.这两条消息合并在一起作为一条消息传入.我的程序只读取前几个字节而忽略了其余的字节.不得不在前面放一个字节来表示消息的大小.一旦到位,我设置了一个while循环来读取它直到它不能再读取. =)感谢大家帮助我.我的第一篇文章,这是一次盛大的经历.

标签:java,multithreading,sockets,2d-games
来源: https://codeday.me/bug/20190711/1432600.html