简体   繁体   English

为什么我的 in.ready() 需要这么长时间?

[英]Why is my in.ready() taking so long?

I'm creating a multiplayer game, which creates a new thread for each client, and then listens on a socket for strings via input and output streams.我正在创建一个多人游戏,它为每个客户端创建一个新线程,然后通过输入和输出流在套接字上侦听字符串。 On the client side I also have a thread separate from the main game thread, but this one will send the updates to the server 60 times per second with a two letter string as the key for what I want to happen.在客户端,我也有一个与主游戏线程分开的线程,但是这个线程每秒将更新发送到服务器 60 次,并以两个字母的字符串作为我想要发生的事情的关键。 When I request my "general update" (code RP) on the client side, the server sends the size of the entity array OK, then there seems to be a very long delay for the stream to become ready again.当我在客户端请求我的“一般更新”(代码 RP)时,服务器发送实体数组的大小 OK,然后流再次准备好似乎有很长的延迟。

I'm relatively sure this is the code of the problem area, after lots of testing to debug.我比较确定这是问题区域的代码,经过大量测试调试。

On the server side:在服务器端:

if(inputLine.equals("RP")){ //this is the main update
            timetoupdate = System.currentTimeMillis(); //start timer
               ArrayList<Player> currentplayers =world.getPlayers(); //get the list of players
                out.println(currentplayers.size()); //send the size
                for(int pl = 0; pl<currentplayers.size();pl++){ //loop through
                    Player player = currentplayers.get(pl); //get the player object
                    out.println(""+pl);
                    out.println(player.getUsername());
                    out.println(player.getType());
                    out.println(player.getXloc());
                    out.println(player.getYloc());
                    out.println(player.getXvel());
                    out.println(player.getYvel());
                    out.println(player.getPressing());
                    out.println(player.getLookingxloc());
                    out.println(player.getLookingyloc());
                    out.println(player.getTeam());
                    out.flush();
                    /*
                     id
                     username
                     class(type)
                     xloc
                     yloc
                     lxloc
                     lyloc
                     */ 
                    // Just gaveout all info on player.getUsername()
                }

                System.out.println("Time this ("+inputLine+") part takes:"+(System.currentTimeMillis()-timetoupdate)); //stop timer

On the Client Side在客户端

out.println("RP"); //tell the server we are generally updating

    String playercountstring = in.readLine(); //get the array size
    int playercount = Integer.valueOf(playercountstring); //convert to int

    for (int i = 0; i < playercount; i++) {//loop through all players

        long timetoupdate = System.currentTimeMillis(); //start timer
        while(!in.ready()){}//wait for input to become ready
        System.out.println("time this (to ready) part takes:"+(System.currentTimeMillis()-timetoupdate));//stop timer


        String toprocess = in.readLine(); //get id of player
... and continues to get all info on this player

As you'll notice I am timing how long the offending areas take to complete: the server takes less than 1 millisecond, yet just that one area of the client takes 200 millisecs, especially weird as the previous line collecting the size of the array takes less than 1 millisecond too.正如你会注意到的,我正在计时完成违规区域需要多长时间:服务器需要不到 1 毫秒,而客户端的一个区域需要 200 毫秒,特别奇怪,因为前一行收集数组的大小需要也小于 1 毫秒。 I'm really at a loss here as to what the issue is, I don't necessarily even need a solution just an explanation would be great.我真的不知道问题是什么,我什至不需要一个解决方案,只是一个解释会很好。 Thanks!谢谢!

There are 2 points in a TCP connection that often cause trouble: TCP连接有2点经常出问题:

  • buffers within Java that gather data before it is handed over to the system, eg within a BufferedOutputStream Java 中的缓冲区,用于在将数据移交给系统之前收集数据,例如在BufferedOutputStream
    • Once the data needs to be sent, you need to call flush()一旦需要发送数据,就需要调用flush()
  • the system's outbound TCP buffer系统的出站 TCP 缓冲区
    • The usual solution is to set the TCP_NODELAY option which disables Nagle's Algorithm that can otherwise delay sending of packets.通常的解决方案是设置TCP_NODELAY选项,该选项禁用Nagle 算法,否则会延迟数据包的发送。 There are other ways as well.还有其他方法

Those places exist on both sides of the connection and both sides.这些地方存在于连接的两侧和两侧。

A little example:一个小例子:

class Server {
    public void serve(int port) throws IOException {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            for(;;) {
                Socket clientSocket = serverSocket.accept();
                clientSocket.setTcpNoDelay(true);
                Thread clientThread = new Thread(() -> handleClient(clientSocket));
                clientThread.start();
            }
        }
    }

    private void handleClient(Socket clientSocket) {
        try (
            Socket socket = clientSocket; // tricks try-with-resource into handling the socket
            OutputStream out = socket.getOutputStream();
            InputStream in = socket.getInputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
             ) {

            while (true) {
                String command = reader.readLine();
                switch (command) {
                    case "quit":
                        Util.send(writer, "ok");
                        return; // ends this thread.
                    case "time":
                        Util.send(writer, String.valueOf(System.currentTimeMillis()));
                        break;
                }
            }

        } catch (IOException e) {
            System.out.println("Client connection closed due to " + e);
            // maybe do something
        }
    }
}

And the client和客户

class Client {
    public void connect(String host, int port) throws UnknownHostException, IOException {
        try (
            Socket socket = new Socket(host, port);
            OutputStream out = socket.getOutputStream();
            InputStream in = socket.getInputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
            ) {

            socket.setTcpNoDelay(true);

            Util.send(writer, "time");
            String time = reader.readLine();
            System.out.println("Server time: " + time);
            Util.send(writer, "quit");
            System.out.println(reader.readLine());
            return;
        }
    }
}

Note how both sides have called socket.setTcpNoDelay(true) .请注意双方如何调用socket.setTcpNoDelay(true) And finally the code to write lines and calls flush() to ensure data isn't stuck in an application level buffer.最后是编写行并调用flush()以确保数据不会卡在应用程序级缓冲区中的代码。

class Util {
    public static void send(BufferedWriter writer, String command) throws IOException {
        writer.write(command);
        writer.newLine();
        writer.flush();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我的 Cloud Run - 到 Firebase 调用要花这么长时间? - Why would my Cloud Run - to Firebase calls be taking so long? 为什么本机libmpg123在android上用libgdx这么长时间? - Why is native libmpg123 taking so long on android with libgdx? 为什么我的应用程序占用了这么多内存? - Why my app is taking so much ram? 为什么只读取一个小文件需要这么长时间? - Why is just reading a small file taking so long? 为什么主键的简单Hibernate findOne()需要这么长时间? - Why is a simple Hibernate findOne() by primary key taking so long? 为什么ical4j需要这么长时间才能构建? - Why is ical4j taking so long to build? 1772年加勒比海在线法官给出时间限制超出错误。 请帮我解释为什么我的算法花了这么长时间 - 1772 of Caribbean online judge giving a time limit exceeded error. please help me find why is my algorithm taking so long 为什么我的BufferedReader不“就绪”? - Why is my BufferedReader not “Ready”? 除了RPC调用之外,我的App Engine程序可能花了这么长时间 - Aside from RPC calls, what could be taking my App Engine Program so long 我怎样才能知道在Tomcat上部署我的WAR这么长时间? - How can I find out what's taking my WAR so long to deploy on Tomcat?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM