5

我在线程中只使用普通的 DataInputStream 和 DataOutputStream 来接收、发送(在服务器上接受)来制作游戏,但它真的很慢。> 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);

对于输入(这个在服务器中),我使用:

(dis 是 DataInputStream,它在 for 循环中,所以 i 是针对每个玩家的)

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();

所以它真的很慢,但我不知道为什么:(请帮忙?

编辑:每个操作(发送、接受、接收)都有自己的守护线程。

4

3 回答 3

7

重复创建DataOutputStreamDataInputStream实例不利于性能。

但是,我怀疑更重要的性能问题是您在没有任何 Java 端缓冲的情况下进行读写。这意味着每个读/写调用都会进行一次(可能还有多次)系统调用来读取数据。系统调用比普通的 Java 方法调用慢几个数量级。

您需要将 Socket 输入流包装在 a 中BufferedInputStream,将输出流包装在 aBufferedOutputStream中,然后将它们包装在 Data 流中。flush(请注意,当您执行此操作时,在每条消息或一系列消息的DataOutputStream末尾添加变得更加重要。


我是否写了一些信息,然后在每次写入后刷新?

就像我上面所说的,您在每条消息或每个消息序列的末尾刷新。假设缓冲区中有要刷新的数据,缓冲输出流上的每次刷新都会导致系统调用。如果您在每次写入时都刷新,那么您(可能)正在执行不必要的系统调用。

由您决定协议的消息边界应该在哪里。这完全取决于您发送/接收的数据的详细信息以及处理方式。

于 2012-05-05T12:57:01.837 回答
2

就像您说的那样,您有一个 for 循环,并为循环中的每次迭代创建一个新的数据输入/输出流。这将导致巨大的开销。

您应该为每个客户端(在单独的线程上)有 1 个数据输入和输出流,然后通过循环构建输入的流来获取用户输入,直到输入流为空。

于 2012-05-05T11:38:37.680 回答
1

当“慢”仅表示网络滞后时,您应该“刷新”您的流以强制传输非完整缓冲区。

添加:

即使这样你也会得到一个像这样的“工作草案”,考虑到一个设计良好的通信协议包含围绕简单命令的各种花里胡哨..问题出现

  • 异常处理
  • 测序
  • 验证
  • 完整性检查(避免作弊、重放……)
  • 可扩展性(新命令,使用显式命令对象)
  • 实时处理
  • 当然还有很多其他人......

有一些框架可以让你摆脱这种负担。

于 2012-05-05T11:35:59.520 回答