Running into what I believe is a networking issue regarding a server/client through the internet.

Started by
14 comments, last by DollaMenunaire 7 years, 5 months ago

You said you're doing this from Android devices. Is this over the mobile network? The latency on those can be unreal sometimes.

I am, at least for now, going to assume wi-fi will always be used. All of my testing has been done with wi-fi. The couple times I tried it without using wi-fi, the response times were steadily 200+ ms.

No, you don't have to. TCP is perfectly fine and will not be the cause of your problem.

You're going to have to show some code, or at least share some technical details. The problem is likely to either be something weird you're doing that incurs this delay, or a slow DNS look-up from the 'NoIP' provider. You can check for the latter by connecting directly to your network's IP address instead of using the provided hostname. (And if it is a slow DNS look-up, it implies you keep making new connections each time, when you should be continuing to use an already-established one.)

I tried going directly to the IP, same issue occurred. I have no problem showing the code, I will post it later tonight.

Advertisement

Sorry about double post, as well as the delay. Wanted to double check some other things prior to responding.

Here is the code. I removed as much outside code to keep this brief and I also wanted to confirm that the outside code was not impacting anything.

Server:


import java.io.*;
import java.net.*;

public class GameMasterServer{
	
	static final int HOSTPORT = 4321;
	int cnt = 0;
	public GameMasterServer()
	{
		OrderServer os = new OrderServer();
		os.start();
	}
	public class OrderServer extends Thread{
	  ServerSocket providerSocket;
	  Socket connection = null;
	
	  BufferedReader inCommand;
	  BufferedWriter outCommand;
	
	  String message;
	  boolean masterServer;
	
	  public OrderServer()
	  {
	    masterServer = true;
	  }
	  public OrderServer(Socket s)
	  {
	    connection = s;
	    masterServer = false;
	  }
	  @Override
	  public void run()
	  {
		  try{
			  if (masterServer) {
				  providerSocket = new ServerSocket(HOSTPORT);
		        OrderServer ls;
		
		        while (true) {
		          ls = new OrderServer(providerSocket.accept());
		          ls.start();
		        }
		      } 
		      else 
		      {
		    	  String line;
		    	  inCommand = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		    	  if((line = inCommand.readLine())!=null)
		    	  {
		    		  outCommand = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
		    		  outCommand.write(line.trim() + System.getProperty("line.separator"));
		    		  outCommand.flush();
		    		  outCommand.close();
		    		  System.out.println(line.trim() + " " + ++cnt);
		    	  }
		      }
		  } 
		  catch (SocketException ex) 	{System.out.println("SOCKET EXCEPTION");} 
		  catch (IOException ex) 		{System.out.println("IOEXCEPTION");} 
		  finally {
			  try { if (providerSocket != null) providerSocket.close(); } catch (Exception ex) {System.out.println("SOCKET NULL ERROR");}
		  }
	  }
	}
}

Client:


    Thread updateThread = new Thread()
    {
        @Override
        public void run() {
            	while(runThreads){
					try {
						sendMessage("Hello Doctor");
					}
					catch (SocketTimeoutException se) {System.out.println("SSDEBUG : DROPPED PACKET");}
					catch (Exception e) {
						System.out.println("SSDEBUG : COMM ERROR");
						e.printStackTrace();
					}
            }
        }
    };

	private String sendMessage(String msg) throws IOException {
		BufferedWriter outCommand;
		BufferedReader inCommand;
		String response;
		Socket hostConnection = new Socket();

		System.out.println("1");
		hostConnection.connect(new InetSocketAddress(StaticVariables.HOSTIP, StaticVariables.HOSTPORT),100);
		outCommand = new BufferedWriter(new OutputStreamWriter(hostConnection.getOutputStream()));
		inCommand  = new BufferedReader(new InputStreamReader(hostConnection.getInputStream()));
		outCommand.write(msg + System.getProperty("line.separator"));
		System.out.println("2");
		outCommand.flush();
		messagesentcount++;
		response = inCommand.readLine();
		System.out.println("3");
		outCommand.close();
		inCommand.close();
		hostConnection.close();
		System.out.println("4");
		return response;
	}    

The problem occurs on the hostConnection.connect. It will hang there (it doesn't now because I attempted a timeout, now it will just timeout constantly for a 15 second span.

To reiterate, the client is on Wi-fi and this problem does not occur whatsoever when using localhost.

The first problem is like I said above: you shouldn't be making a new connection each time you send a message. That's like buying a new car each time you want to go somewhere and selling it when you arrive. Create the socket and connect it exactly once, and leave it connected until the thread finishes. Then see if your problem persists.

Good example on the cost of new connections. Worst case can be severe; perhaps the device isn't caching the names and a full DNS lookup is required every time, requiring multiple round trips to multiple remote sources every connection attempt.

But the delay may have other causes.

As for the delay, even when reusing connections I've seen some mobile device connections where network communications really are awful. It may be the device's particular networking stack or terrible changes that were made moving to the device or other background apps or filters on the device, but in my experience Android devices chosen at random are abysmal at networking. It doesn't even need to be their cellular network (which adds another layer of potentially terrible delays). One device may perform amazingly fast, another stalls for many seconds for data that Wireshark says was sent ages ago. I've seen messages sent through WiFi where for seemingly unfathomable reasons require over 20 seconds to be processed in the application on some devices.

Make sure you've got a range of devices for testing, not just one device.

Good example on the cost of new connections. Worst case can be severe; perhaps the device isn't caching the names and a full DNS lookup is required every time, requiring multiple round trips to multiple remote sources every connection attempt.

But the delay may have other causes.

As for the delay, even when reusing connections I've seen some mobile device connections where network communications really are awful. It may be the device's particular networking stack or terrible changes that were made moving to the device or other background apps or filters on the device, but in my experience Android devices chosen at random are abysmal at networking. It doesn't even need to be their cellular network (which adds another layer of potentially terrible delays). One device may perform amazingly fast, another stalls for many seconds for data that Wireshark says was sent ages ago. I've seen messages sent through WiFi where for seemingly unfathomable reasons require over 20 seconds to be processed in the application on some devices.

Make sure you've got a range of devices for testing, not just one device.

Interesting. I have been testing with 4 devices, ranging from 5 years old to 1 year old. They've at least been consistent in having this problem, which is a good thing of sorts.

The first problem is like I said above: you shouldn't be making a new connection each time you send a message. That's like buying a new car each time you want to go somewhere and selling it when you arrive. Create the socket and connect it exactly once, and leave it connected until the thread finishes. Then see if your problem persists.

Will do and I'll report back tonight if I figure it out, thanks.

They've at least been consistent in having this problem, which is a good thing of sorts.


Wireshark will tell you what the device and the host are doing while that happens, assuming you can tap the network at the right place.
It's often useful to hook a linux box between your wireless gateway and your upstream internet connection, configured to do NAT, so that you can capture this.
(The wireless gateway then should be in bridge mode, and the DHCP / NAT server should be on the LInux box.)
enum Bool { True, False, FileNotFound };

The first problem is like I said above: you shouldn't be making a new connection each time you send a message. That's like buying a new car each time you want to go somewhere and selling it when you arrive. Create the socket and connect it exactly once, and leave it connected until the thread finishes. Then see if your problem persists.

This did it, thanks a lot for the help.

It's still a bit rough so I'll still have to clean up the connect/disconnect cases but the problem is absolutely gone.

I'll post back if I have any other questions but I think I'm good for now.

Thanks everyone else who pitched in as well.

This topic is closed to new replies.

Advertisement