我的java套接字代码有点问题。 我正在编写一个android客户端应用程序,它通过直接(!)无线连接将数据发送到我的电脑上的java多线程套接字服务器。它工作正常,但我想为移动应用程序改进它,因为它现在非常耗电。当我在我的代码中删除两个特殊行时,我的移动设备(htc one x)的cpu使用情况完全没问题但是我的连接似乎有很高的ping率或类似的东西......
这是我收到客户数据的服务器代码段:
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
答案 0 :(得分:1)
代码的CPU密集型版本会使输出流充满null
值。它们被视为要传输的数据。尽管您的服务器明确忽略了它们,但它们最终也会帮助最终强制执行任何有用的数据。
使用peek
修改后的代码更合理。在flush
之后调用writeObject
是一种很好的形式。否则,写入的对象可能会卡在输出缓冲区中并等待更多项目到来。缓冲是对许多对象一起发送的情况的性能优化。不进行缓冲的流类不需要刷新。
更好:
Object item = sendQueue.poll();
if (item != null) {
out.writeObject(item);
out.flush(); // maybe not needed, depending on the class of your stream
}
这稍快一些;如果您打算立即peek
,那么评估poll
毫无意义。
此外,在将套接字传递给socket.setTcpNoDelay(true)
之前,请在套接字上调用SocketOutputStream
(假设您创建输出流的方式)。这会禁用Nagle algorithm,这可能不一定是保护网络带宽的最佳决策,但它是一种快速检查除了调整TCP发送/接收缓冲区以外的客户端和服务器正常工作的方法。如果您直接连接到服务器,我根本不用担心会禁用Nagle算法。
答案 1 :(得分:0)
您应该使用阻塞队列,以便poll()阻止,而不是返回null。发送空值毫无意义,这只是浪费每个人的时间,带宽和金钱。
答案 2 :(得分:0)
另外请注意,您可能需要查看适用于Android的ARO工具,它可以帮助您优化应用,包括网络使用。 http://developer.att.com/developer/legalAgreementPage.jsp?passedItemId=9700312