Sign in to follow this  

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

This topic is 411 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys and gals. I'll try and keep this as concise as possible while giving all the necessary details. This is regarding a game but I believe that this isn't necessarily a 'game' issue.

 

So I'm essentially making an Android game which communicates to a server (which is now my computer). The app will continuously request for updates from the server, and the server will collect the current game status and send it back to the client. 

 

So, I got everything working while using a local ip. Then I investigated how to make a server out of my computer (This part I am very new to). So I used noip.com to set up a host dns, and set port forwarding on my router to send all data going to the port to my PC. 

 

So now it's at the point where the android devices communicate to my PC through the hostname. However, after about a minute or so, the android device will send a message, but it will take 1-2 seconds for the server to see it. Then shortly after this begins, the connection will hang for 15-20 seconds at a time. 

 

Things I've ruled out so far:

 

1) I've tried using my outside ip to send the messages instead of the hostname, same problem.

2) Doing a speedtest, I have 30 mb down and 6 mb up, so I think that's ok. These messages are presumably much smaller than other games (50 bytes back and forth) and I do a good amount of online gaming with no issue.

3) ping testing the hostname for an hour and the highest ping time was 2ms, which is much less than what I'm seeing. 

4) I did confirm that neither side is hanging up, the android device is sending the message and then waits for the return, and the server is still waiting to see the message. 

5) Switching back to localhost and I don't have this lag issue whatsoever.

6) I did some research on windows firewalls to confirm as best I can it's not interfering. 

 

I'll gladly share any code/network information I can provide, but I'm not sure what would be beneficial right now, given the clues I have. 

 

My next test will be testing this on a raspberry pi, but that will wait until tomorrow. 

 

Thanks.  :D

Edited by DollaMenunaire

Share this post


Link to post
Share on other sites
It sounds like you have a code bug somewhere.
Use Wireshark to look for packets sent to your particular port.
Separately:

The app will continuously request for updates from the server


If a "connection" exists, you can assume that the player wants the world state.
You don't need to have the client "request" the data.
Instead, the client should send "I'm alive, and here's my next input commands" messages X times per second, and the server should send "here's the latest world update and commands from all the other players" Y times per second.
The server can then look at the incoming stream, and if it hasn't seen anything from the player for something between 3 and 30 seconds, assume the client has disconnected.
Same thing for the client; if it doesn't see anything from the server for a timeout period, assume the connection has dropped.

Share this post


Link to post
Share on other sites

It sounds like you have a code bug somewhere.
Use Wireshark to look for packets sent to your particular port.
 

Instead, the client should send "I'm alive, and here's my next input commands" messages X times per second, and the server should send "here's the latest world update and commands from all the other players" Y times per second.
The server can then look at the incoming stream, and if it hasn't seen anything from the player for something between 3 and 30 seconds, assume the client has disconnected.
Same thing for the client; if it doesn't see anything from the server for a timeout period, assume the connection has dropped.

 

 

I'll check wireshark if not tonight tomorrow. But the 2nd part of your post describes how the messages are actually sent back and forth, I think I didn't describe it too well. 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Agree with Khatharr.  I am a professional Network Engineer (although not for a Telco) and latency over mobile networks can be very erratic.  Your occasional 1-2 seconds could be related to this but the 15-20 seconds does not.  No packet should take that long (even Earth to the moon is about 1.3 seconds).

 

Switching to UDP would not help in this case.

 

Most likely there is some kind of bug in your networking code itself that causes these errors to pop up?  Are your sockets blocking?  If so, what is the timeout set on them?  Example: lets say you set 5 seconds as a timeout, and you send a packet from the sender to a receiver but it gets lost/dropped along the way, you wait 5 seconds and resend, it gets lost, you wait 5 seconds and send again and it makes it.....there is 15 seconds there due to 2 consecutive lost transmissions.  Lost/dropped packets on mobile are much higher than other networks as well.

Share this post


Link to post
Share on other sites
Note that "15 seconds latency" could be something as simple as "getting the framing of individual packets on a TCP connection wrong, and thus packets run into each other and the recv() call blocks."
For a newbie to network programming, there are so many things that can go wrong at the basic API level, it's hard to diagnose from a simple high-level self-reported symptom like that.

Share this post


Link to post
Share on other sites

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. 

Share this post


Link to post
Share on other sites

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. 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

This topic is 411 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this