UDP network getting stuck

Started by
1 comment, last by Canvas 11 years ago

Hey there people of GameDev community, I've been trying to fix this really annoying problem, but so far I have not been able to budge it what so ever, so first off here is the example that I am using.

A Android device will start as the host, it will listen on a port for 200ms, this port is used for the client to send the message "connect" when this is received, it will send out an ID to the client, take the address and then move on, it then waits to received the block position from the player which comes in the format of 1:100:100

ID:Xvalue:Yvalue, when the client is connected to the server it will constantly send this out, once it has that, it will then move on to send all the positions on the server to all the clients connected,

Here is what happens, the server starts, and the sockets timeout when they need to, this is to stop the whole server from just hanging, when a client goes to connect, nothing happens, the client will just sit there trying to connect, and the server will print out in the console that it has received connect, but it does nothing with it.

Here is my code for the server


while( run )
		{
			/*addresses = gsID.addresses;
				gsPos.addresses = addresses;
				gsSendPos.addresses = addresses;
				gsSendPos.positions = gsPos.positions;*/
			//GameServerID
			try
			{
				boolean dataGot = false;
				if(gameServerID == null)
				{
					gameServerID = new DatagramSocket( portID );
				}
				//try to receive data
				byte[] buf = new byte[256];
				DatagramPacket packet = new DatagramPacket( buf, buf.length );
				try
				{
					Log.d(TAG, "Wait for a client to connect");
					gameServerID.setSoTimeout( 200 );
					gameServerID.receive( packet );
					dataGot = true;
				}
				catch (IOException e) 
				{
					Log.d(TAG, "Error with receiving data");
					e.printStackTrace();
				}
				String data = new String( buf, 0, packet.getLength() );
				if( dataGot == true )
				{
					Log.d(TAG, data);
				}
				//Send out the ID to the client
				byte[] bufer = new byte[256];
				//Send a message "connect" to the host
				String msg = Integer.toString( players );
				players = players + 1;
				bufer = msg.getBytes();
				InetAddress address;
				//Default ip address of the host
				address = packet.getAddress();
				DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, portID );
				//Send packet
				gameServerID.send( p );
				addresses.add( address );
			}
			catch (SocketException e) 
			{
				Log.d(TAG, "Error with socket");
				e.printStackTrace();
			} 
			//Listen for a client to connect
			catch (IOException e) 
			{
				Log.d(TAG, "Error with I/O");
				e.printStackTrace();
			}

			//GameServerPositions
			try
			{
				boolean dataGot2 = false;
				Log.d(TAG, "Run the gamePositions code");
				if(gamePositions == null)
				{
					gamePositions = new DatagramSocket( portPos );
				}
				//Receive position
				//try to receive data
				byte[] buf = new byte[256];
				DatagramPacket packet = new DatagramPacket( buf, buf.length );
				try
				{
					gamePositions.setSoTimeout( 200 );
					gamePositions.receive( packet );
					dataGot2 = true;
				}
				catch (IOException e) 
				{
					Log.d(TAG, "Error with receiving data");
					e.printStackTrace();
				}
				String data = new String( buf, 0, packet.getLength() );

				if( dataGot2 == true )
				{
					Log.d(TAG, data);
					String[] pos = data.split(":");
					for(int i = 0;i<pos.length;i++)
					{
						Log.d(TAG, pos);
					}
					xValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[1] );
					yValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[2] );
				}
			}
			catch (SocketException e) 
			{
				Log.d(TAG, "Error with socket");
				e.printStackTrace();
			} 
			//Listen for a client to connect
			catch (IOException e) 
			{
				Log.d(TAG, "Error with I/O");
				e.printStackTrace();
			}

			//GameServerSendPos
			try
			{
				Log.d(TAG, "Run the gamePositionsSend code");
				String data = "";
				if( gameSendPos == null )
				{
					gameSendPos = new DatagramSocket( portSend );
				}

				//create the string ready to be sent out
				for(int i = 0; i < 8; i++)
				{
					if(xValues >= 0)
					{
						data += i + ":" + xValues + ":" + yValues + ":";
					}
				}

				byte[] bufer = new byte[256];
				bufer = data.getBytes();
				DatagramPacket p = null;

				for(int i = 0;i < addresses.size(); i++)
				{
					if( addresses.get(i) != null )
					{
						p = new DatagramPacket( bufer, bufer.length , addresses.get(i), portSend );
						gameSendPos.send( p );
					}
				}

			}
			catch (SocketException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} //End of while statement

I have tried to to create all of those try statements into their own classes, but as they are Asynctask only the first one called will do work, the other two below will never start until the first is is actually finished, which is never because it needs to listen for socket.receive.

If anyone could give me a hand that would be great, I've been stuck on this for some time now, and I really want to fix it.

Cheers for reading and also thank you for commenting

Canvas

P.S.

here is the out put on the LogCat from the server phone oohh and also sometimes the client does connect, but this is not 100% if you want the client code, just let me know and I will upload it.


04-04 14:14:54.093: D/GameServer(15201): Wait for a client to connect
04-04 14:14:54.296: D/GameServer(15201): Error with receiving data
04-04 14:14:54.304: D/GameServer(15201): Run the gamePositions code
04-04 14:14:54.511: D/GameServer(15201): Error with receiving data
04-04 14:14:54.515: D/GameServer(15201): Run the gamePositionsSend code
04-04 14:14:54.515: D/GameServer(15201): Wait for a client to connect
04-04 14:14:54.519: D/GameServer(15201): connect
04-04 14:14:54.519: D/GameServer(15201): Run the gamePositions code
04-04 14:14:54.558: D/GameServer(15201): 7:250:300
04-04 14:14:54.558: D/GameServer(15201): 7
04-04 14:14:54.558: D/GameServer(15201): 250
04-04 14:14:54.558: D/GameServer(15201): 300
04-04 14:14:54.558: D/GameServer(15201): Run the gamePositionsSend code

this is what is printed out if a client does actually get to connect, the data is a little wrong, but my main problem is the client not always being able to connect.

Advertisement

seems like your code is just way over-complicated while failing to deal with the fact that UDP is an unreliable-protocol, meaning, there is no guarantee that a sent packet will be seen on the other side (due to the inherent low-level instability of sending massive amounts of bits over copper wires, or wirelessly, collisions, etc)..

You need to be tracking the state of the server, and the state of remote clients, in terms of where they are with their connection (handshaking, sending game information, actively relaying game states, etc)... which isn't as simple as just making a list of things to do, you have to treat each state individually, and detect the context in which that state was achieved to validate it.

Try using TCP, if you're not comfortable with the idea of information not making it to the other site.. The catch with TCP is that packets sent don't necessarily arrive as "packets", they can be fragmented and/or clumped with other sent packets upon arrival... but they will always arrive in-order. The trick is to use a byte to indicate the length of the message, at the very beginning/end of your packets, so that it can be properly reconstituted at the other side.

I'm using UDP as it is quick and fast compared to TCP, and I understand TCP, I want to try and understand UDP, also this error is fixed now, but the problem I have now is my server is really laggy, and clients can connect no problem, move about, but it takes forever for the server to actually send out the new data received by the clients connect, it takes about 3 seconds, and still the movement is the server doinbackgound code


while( run )
		{
			/*addresses = gsID.addresses;
				gsPos.addresses = addresses;
				gsSendPos.addresses = addresses;
				gsSendPos.positions = gsPos.positions;*/
			//GameServerID
			try
			{
				boolean dataGot = false;
				if(gameServerID == null)
				{
					gameServerID = new DatagramSocket( portID );
				}
				//try to receive data
				byte[] buf = new byte[256];
				DatagramPacket packet = new DatagramPacket( buf, buf.length );
				try
				{
					//Log.d(TAG, "Wait for a client to connect");
					gameServerID.setSoTimeout( 1 );
					gameServerID.receive( packet );
					dataGot = true;
				}
				catch (IOException e) 
				{
					//Log.d(TAG, "Error with receiving data");
					e.printStackTrace();
				}
				String data = new String( buf, 0, packet.getLength() );
				if( dataGot == true )
				{
					//Log.d(TAG, data);
				//Send out the ID to the client
				byte[] bufer = new byte[256];
				//Send a message "connect" to the host
				String msg = Integer.toString( players );
				players = players + 1;
				bufer = msg.getBytes();
				InetAddress address;
				//Default ip address of the host
				address = packet.getAddress();
				DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, portID );
				//Send packet
				gameServerID.send( p );
				addresses.add( address );
				}
			}
			catch (SocketException e) 
			{
				Log.d(TAG, "Error with socket");
				e.printStackTrace();
			} 
			//Listen for a client to connect
			catch (IOException e) 
			{
				Log.d(TAG, "Error with I/O");
				e.printStackTrace();
			}

			//GameServerPositions
			try
			{
				boolean dataGot2 = false;
				//Log.d(TAG, "Run the gamePositions code");
				if(gamePositions == null)
				{
					gamePositions = new DatagramSocket( portPos );
				}
				//Receive position
				//try to receive data
				byte[] buf = new byte[256];
				DatagramPacket packet = new DatagramPacket( buf, buf.length );
				try
				{
					//1
					gamePositions.setSoTimeout( 1 );
					gamePositions.receive( packet );
					dataGot2 = true;
				}
				catch (IOException e) 
				{
					Log.d(TAG, "Error with receiving data");
					e.printStackTrace();
				}
				String data = new String( buf, 0, packet.getLength() );

				if( dataGot2 == true )
				{
					//Log.d(TAG, data);
					String[] pos = data.split(":");
					for(int i = 0;i<pos.length;i++)
					{
						//Log.d(TAG, pos);
					}
					xValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[1] );
					yValues[ Integer.parseInt( pos[0] ) ] = Integer.parseInt( pos[2] );
				}
			}
			catch (SocketException e) 
			{
				Log.d(TAG, "Error with socket");
				e.printStackTrace();
			} 
			//Listen for a client to connect
			catch (IOException e) 
			{
				Log.d(TAG, "Error with I/O");
				e.printStackTrace();
			}

			//GameServerSendPos
			try
			{
				//Log.d(TAG, "Run the gamePositionsSend code");
				String data = "";
				if( gameSendPos == null )
				{
					gameSendPos = new DatagramSocket( portSend );
				}

				//create the string ready to be sent out
				for(int i = 0; i < 8; i++)
				{
					if(xValues >= 0)
					{
						data += i + ":" + xValues + ":" + yValues + ":";
						//Log.d(TAG, "data to be sent out : " + data);
					}
				}
				//Log.d(TAG, "data finished");

				byte[] bufer = new byte[256];
				bufer = data.getBytes();
				DatagramPacket p = null;

				for(int i = 0;i < addresses.size(); i++)
				{
					if( addresses.get(i) != null )
					{
						p = new DatagramPacket( bufer, bufer.length , addresses.get(i), portSend );
						gameSendPos.send( p );
					}
				}

			}
			catch (SocketException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} //End of while statement

Any easy way for me to change something to stop the server from being so laggy?

This topic is closed to new replies.

Advertisement