我只是在线程中使用普通的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);对于输入(这个在服务器中),我使用:
(dis是DataInputStream,它在一个for循环中,所以我是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();所以它真的很慢,但我不知道为什么:(请帮帮忙?
编辑:每个操作(发送、接受、接收)都有自己的守护线程。
发布于 2012-05-05 20:57:02
重复创建DataOutputStream和DataInputStream实例不利于性能。
然而,我怀疑更重要的性能问题是您在读写时没有任何Java端缓冲。这意味着每次读/写调用都会进行一次(也可能是多次)syscall来读取数据。系统调用比普通Java方法调用慢几个数量级。
您需要将套接字输入流包装在BufferedInputStream中,将输出流包装在BufferedOutputStream中,然后将它们包装在数据流中。(请注意,执行此操作时,更重要的是在每条消息或一系列消息的末尾执行flush DataOutputStream。
是否要写入一些信息,然后在每次写入后刷新?
正如我上面所说的,您可以在每个消息或每个消息序列的末尾刷新。假设缓冲区中有数据要刷新,则缓冲输出流上的每次刷新都将导致syscall。如果您在每次写入时都刷新,那么您(可能)正在执行不必要的syscall。
由您来确定您的协议的消息边界应该在哪里。这完全取决于您正在发送/接收的数据的详细信息,以及处理这些数据的方式。
发布于 2012-05-05 19:38:38
正如您所说,您有一个for循环,并为循环中的每个迭代创建一个新的数据输入/输出流。这将导致巨大的开销。
您应该为每个客户端(在单独的线程上)提供1个数据输入流和输出流,然后通过循环此流来获取用户输入,构建输入,直到输入流为空。
发布于 2012-05-05 19:36:00
当您所说的“慢”只是指网络滞后时,那么您应该“刷新”您的流,以强制非满缓冲区的传输。
添加:
即使这样,你也会得到一个像这样进行的“工作草案”,考虑到一个设计良好的通信协议包含了关于普通命令的各种花哨的东西。出现的问题如下
实时异常handling
有一些框架可以让你摆脱这个负担。
https://stackoverflow.com/questions/10461302
复制相似问题