我在线程中使用普通的DataInputStream和DataOutputStream进行接收,发送(使用服务器上的accept)来制作游戏,但它确实很慢。 > 5秒滞后。
以下是我制作它的方式(大部分看起来都是这样):
(dos是DataOutputStream)
dos = new DataOutputStream(socket.getOutputStream());
dos.writeFloat(dp.x);
dos = new DataOutputStream(socket.getOutputStream());
dos.writeFloat(dp.y);
dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(dp.username);
对于Input(这个在服务器中),我使用:
(dis是DataInputStream,它在for循环中,所以我是每个玩家)
dis = new DataInputStream(list_sockets.get(i).getInputStream());
x = dis.readFloat();
dis = new DataInputStream(list_sockets.get(i).getInputStream());
y = dis.readFloat();
dis = new DataInputStream(list_sockets.get(i).getInputStream());
username = dis.readUTF();
所以它真的很慢,但我不知道为什么:( 请帮帮忙?
编辑:每个操作(发送,接受,接收)都有自己的守护程序线程。
答案 0 :(得分:6)
反复创建DataOutputStream
和DataInputStream
个实例对性能不利。
但是,我怀疑更重要性能问题是您在没有任何Java端缓冲的情况下进行读写。这意味着每次读/写调用都会使一个(可能很多)系统调用来读取数据。系统调用比普通的Java方法调用慢几个数量级。
您需要将Socket输入流包含在BufferedInputStream
中,将输出流包含在BufferedOutputStream
中,然后将它们包装在数据流中。 (请注意,执行此操作时,在每封邮件或一系列邮件末尾flush
DataOutputStream
变得更加重要。
我是否写了一些信息,然后在每次写入后刷新?
就像我上面所说的那样,你会在每条消息或每个消息序列的末尾刷新。假设缓冲区中有数据要刷新,缓冲输出流上的每次刷新都将导致系统调用。如果你在每次写入时都刷新(可能)正在进行不必要的系统调用。
由您决定协议的消息边界应该在哪里。它完全取决于您发送/接收的数据的详细信息以及处理方式。
答案 1 :(得分:2)
就像你说你有一个for循环并为循环中的每次迭代创建一个新的数据输入/输出流。这将导致巨大的开销。
每个客户端(在一个单独的线程上)应该有1个数据输入和输出流,然后通过循环构建输入的流来获取用户输入,直到输入流为空。
答案 2 :(得分:1)
如果“慢”只表示网络滞后,那么您应该“刷新”您的流以强制运行非完整缓冲区。
增加:
即使如此,你也会得到一个像这样的“工作草案”,考虑到一个设计良好的通信协议包含普通命令周围的各种铃声和口哨声。问题就像
有一些框架可以帮助您避免这种负担。