Java套接字连接正在淹没网络或导致高ping
我的java套接字代码有点问题。 我正在编写一个android客户端应用程序,它通过直接(!)无线连接将数据发送到我电脑上的java多线程套接字服务器。它工作得很好,但我想为移动应用改进它,因为它现在非常耗电。当我删除代码中的两行特殊代码时,我的移动设备(htc one x)的cpu使用率是完全正常的,但是我的连接似乎有很高的ping速率或者类似的东西 下面是一个服务器代码片段,我在其中接收客户端数据:Java套接字连接正在淹没网络或导致高ping,java,android,sockets,connection,wireless,Java,Android,Sockets,Connection,Wireless,我的java套接字代码有点问题。 我正在编写一个android客户端应用程序,它通过直接(!)无线连接将数据发送到我电脑上的java多线程套接字服务器。它工作得很好,但我想为移动应用改进它,因为它现在非常耗电。当我删除代码中的两行特殊代码时,我的移动设备(htc one x)的cpu使用率是完全正常的,但是我的连接似乎有很高的ping速率或者类似的东西 下面是一个服务器代码片段,我在其中接收客户端数据: while(true) { try { .
while(true)
{
try {
....
Object obj = in.readObject();
if(obj != null) {
Class clazz = obj.getClass();
String className = clazz.getName();
if(className.equals("java.lang.String")) {
String cmd = (String)obj;
if(cmd.equals("dc")) {
System.out.println("Client "+id+" disconnected!");
Server.connectedClients[id-1] = false;
break;
}
if(cmd.substring(0,1).equals("!")) {
robot.keyRelease(PlayerEnum.getKey(cmd,id));
}
else {
robot.keyPress(PlayerEnum.getKey(cmd,id));
}
}
}
} catch ....
这是客户端部分,我在while循环中发送数据:
private void networking() {
try {
if(client != null) {
....
out.writeObject(sendQueue.poll());
....
}
} catch ....
当我写这篇文章时,每当while循环执行时,我都会发送数据。。当sendQueue为空时,将发送空的“对象”。这会导致“高”网络流量和“高”cpu使用率。但是:所有发送评论几乎都会立即收到
当我将代码更改为以下内容时:
while(true)
...
if(sendQueue.peek() != null) {
out.writeObject(sendQueue.poll());
}
...
cpu使用率完全正常,但我有一些滞后。。命令到达的速度不够快。。正如我所说的,如果我在每次执行时发送数据(使用空对象),那么它工作得很好(除了cpu使用情况)。但我确信这是一种非常粗糙的编码风格,因为我有点像洪水一样淹没了整个网络。有什么提示吗
我做错了什么
谢谢你的帮助 真诚地属于你,
maaft您的代码的CPU密集型版本正在向输出流中注入
null
值。它们被视为要传输的数据。尽管您的服务器明确地忽略了它们,但它们也有助于最终强制任何有用的数据通过
用peek
修改代码更合理。在writeObject
之后调用flush
是一种很好的形式。否则,写入的对象可能会卡在输出缓冲区中,等待更多的项出现。对于多个对象一起发送的情况,缓冲是一种性能优化。不进行缓冲的流类不需要刷新
更好的是:
Object item = sendQueue.poll();
if (item != null) {
out.writeObject(item);
out.flush(); // maybe not needed, depending on the class of your stream
}
这稍微快一点;如果您打算立即进行poll
,那么评估peek
是没有意义的
此外,在将套接字传递给
SocketOutputStream
之前,在套接字上调用socket.setTcpNoDelay(true)
(假设这就是创建输出流的方式)。这会禁用,这可能不一定是节约网络带宽的最佳决策,但它是一种快速的方法,可以检查除了调整TCP发送/接收缓冲区之外,客户端和服务器是否正常工作。如果您直接连接到服务器,我根本不担心禁用Nagle算法。您的代码的CPU密集型版本正在向输出流中注入null
值。它们被视为要传输的数据。尽管您的服务器明确地忽略了它们,但它们也有助于最终强制任何有用的数据通过
用peek
修改代码更合理。在writeObject
之后调用flush
是一种很好的形式。否则,写入的对象可能会卡在输出缓冲区中,等待更多的项出现。对于多个对象一起发送的情况,缓冲是一种性能优化。不进行缓冲的流类不需要刷新
更好的是:
Object item = sendQueue.poll();
if (item != null) {
out.writeObject(item);
out.flush(); // maybe not needed, depending on the class of your stream
}
这稍微快一点;如果您打算立即进行poll
,那么评估peek
是没有意义的
此外,在将套接字传递给
SocketOutputStream
之前,在套接字上调用socket.setTcpNoDelay(true)
(假设这就是创建输出流的方式)。这会禁用,这可能不一定是节约网络带宽的最佳决策,但它是一种快速的方法,可以检查除了调整TCP发送/接收缓冲区之外,客户端和服务器是否正常工作。如果您直接连接到服务器,我根本不担心禁用Nagle算法。您应该使用阻塞队列,以便poll()阻塞,而不是返回null。发送null没有任何意义,这只是浪费每个人的时间、带宽和金钱。您应该使用阻塞队列,以便poll()阻塞,而不是返回null。发送空值没有任何意义,这只是浪费每个人的时间、带宽和金钱。作为进一步说明,您可能想看看Android的ARO工具,它可以帮助您优化应用程序,包括网络使用情况 作为进一步说明,您可能想看看Android的ARO工具,它可以帮助您优化应用程序,包括网络使用情况 谢谢你的快速回答!我已经用flush()方法尝试过了,但是我的命令仍然很晚才到达。奇怪的是,泛滥的网络导致命令几乎立即到达。可能是因为套接字需要一点时间对“新”数据而不是稳定的数据流作出反应??我无法指出..@user1461100-您如何准确构建所涉及的输出流?也就是说,它们是什么类型的,你对它们设置了什么或传递给它们的构造函数?@user1461100-我将在这一天剩下的时间里离线,但我添加了将Nagle算法关闭为问题的指导,希望这可能是你的问题。谢谢你,你是天才!禁用Nagle算法完全解决了我的问题!:)谢谢你的快速回答!我已经用flush()方法尝试过了,但是我的命令仍然很晚才到达。奇怪的是,泛滥的网络导致命令几乎立即到达。可能是因为套接字需要一点时间对“新”数据而不是稳定的数据流作出反应??我无法指出..@user1461100-您如何准确构建所涉及的输出流?Th