user1461100
user1461100

Reputation: 21

Java Socket Connection is flooding network OR resulting in high ping

i have a little problem with my java socket code. I'm writing an android client application which is sending data to a java multithreaded socket server on my pc through direct(!) wireless connection. It works fine but i want to improve it for mobile applications as it is very power consuming by now. When i remove two special lines in my code, the cpu usage of my mobile device (htc one x) is totally okay but then my connection seems to have high ping rates or something like that...

Here is a server code snippet where i receive the clients data:

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 ....

Heres the client part, where i send my data in a while loop:

private void networking() {
    try {
        if(client != null) {
            ....
                out.writeObject(sendQueue.poll());

            ....
        }
    } catch ....

when i write it this why, i send data everytime the while loop gets executed.. when sendQueue is empty, a null "Object" will be send. this results in "high" network traffic and in "high" cpu usage. BUT: all send comments are received nearly immediately.

when i change the code to following:

while(true)
...
if(sendQueue.peek() != null) {
    out.writeObject(sendQueue.poll());
}
...

the cpu usage is totally okay but i'm getting some laggs.. the commands do not arrive fast enough.. as i said, it works fine (besides cpu usage) if i'm sending data(with that null objects) every while execution. but i'm sure that this is very rough coding style because i'm kind of flooding the network. any hints?

what am i doing wrong??


Thanks for your Help!

Sincerly yours, maaft

Upvotes: 1

Views: 1020

Answers (3)

Rod Burns
Rod Burns

Reputation: 2244

Just as a further note, you might want to take a look at the ARO tool for Android that helps you to do optimization of your app including network usage. http://developer.att.com/developer/legalAgreementPage.jsp?passedItemId=9700312

Upvotes: 0

user207421
user207421

Reputation: 311028

You should use a blocking queue so that poll() blocks, rather than returning null. There is no point in sending the nulls at all, it's just a waste of everybody's time, bandwidth, and money.

Upvotes: 0

Jirka Hanika
Jirka Hanika

Reputation: 13549

The CPU-intensive version of your code is flooding the output stream with null values. They count as data to be transmitted. Although your server explicitly ignores them, they are helping to to eventually force any useful data through as well.

Your modified code with the peek is more reasonable. It is good form to call flush after writeObject. The written object could otherwise be stuck in output buffers and waiting for more items to come. Buffering is a performance optimization for cases where many objects are sent together. Flushing is not needed with stream classes that do not do buffering.

Even better:

Object item = sendQueue.poll();
if (item != null) {
    out.writeObject(item);
    out.flush();  // maybe not needed, depending on the class of your stream 
}

This is slightly faster; there is no point in evaluating peek if you intend to poll immediately anyway.

Furthermore, call socket.setTcpNoDelay(true) on the socket before you pass it to the SocketOutputStream (assuming that is how you create the output streams). That disables the Nagle algorithm which may not necessarily be the best decision for conservation of network bandwidth, but it is a quick way to check that apart from tuning TCP send/receive buffers your client and server work correctly. If you have a direct connection to your server I would not worry about disabling Nagle algorithm at all.

Upvotes: 1

Related Questions