I've been working on a UDP android server for some time, and at last, it works, it allows multiple clients to connect, they can move their block around the screen, and everyone connected can see, but my issue is, when a client moves it is instant on their screen, but on another clients screen, it doesn't happen until about 3seconds later, now I know this is a server issue, I think I know where the issue is but I'm not sure how I can try and fix it, my server uses 3 different ports, one to receive a message so a client wants to join, one port to allow clients to send their position, and one more port to send out the position of the clients connected blocks, so clients can update their game,
Here is my server code
[HIGH]
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
{
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
[/HIGH]
gameServerID has a 1 millisecond timeout to stop the server from just stopping, I tried to implement it in a class using AsyncTask but the method just kept in its loop and didn't allow the other methods to run, I tried a Thread but android 4.0 and above doesn't like this because of UI and Threads. What it seems is happening is, gameServerID and gamePositions both have a setTimeOut(1), so both of them will listen for 1 millisecond, this allows for clients to join, and send their position to the server, but doing so SLAMS the server into a slug mode, and positions are sent out to the clients very, very slowly, here is a piece of the logcat output screen from the host
[HIGH]
04-05 02:49:42.093: D/dalvikvm(16836): JIT unchain all for threadid=11
04-05 02:49:42.140: D/dalvikvm(16836): GC_CONCURRENT freed 511K, 59% free 2756K/6663K, external 1657K/2137K, paused 2ms+2ms
04-05 02:49:42.148: W/System.err(16836): java.net.SocketTimeoutException: Try again
04-05 02:49:42.148: W/System.err(16836): at org.apache.harmony.luni.platform.OSNetworkSystem.recv(Native Method)
04-05 02:49:42.152: W/System.err(16836): at dalvik.system.BlockGuard$WrappedNetworkSystem.recv(BlockGuard.java:321)
04-05 02:49:42.156: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:172)
04-05 02:49:42.156: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:181)
04-05 02:49:42.156: W/System.err(16836): at java.net.DatagramSocket.receive(DatagramSocket.java:402)
04-05 02:49:42.160: W/System.err(16836): at com.example.gelorph_v1.gameServer.doInBackground(gameServer.java:139)
04-05 02:49:42.160: W/System.err(16836): at com.example.gelorph_v1.gameServer.doInBackground(gameServer.java:1)
04-05 02:49:42.160: W/System.err(16836): at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-05 02:49:42.160: W/System.err(16836): at java.lang.Thread.run(Thread.java:1019)
04-05 02:49:42.167: W/System.err(16836): java.net.SocketTimeoutException: Try again
04-05 02:49:42.167: W/System.err(16836): at org.apache.harmony.luni.platform.OSNetworkSystem.recv(Native Method)
04-05 02:49:42.167: W/System.err(16836): at dalvik.system.BlockGuard$WrappedNetworkSystem.recv(BlockGuard.java:321)
04-05 02:49:42.171: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:172)
04-05 02:49:42.171: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:181)
04-05 02:49:42.171: W/System.err(16836): at java.net.DatagramSocket.receive(DatagramSocket.java:402)
[/HIGH]
If anyone could help me fix this last bug, it would be awesome.
Canvas
If you want more snippets of my code just let me know.
Here is my server code
[HIGH]
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
{
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
[/HIGH]
gameServerID has a 1 millisecond timeout to stop the server from just stopping, I tried to implement it in a class using AsyncTask but the method just kept in its loop and didn't allow the other methods to run, I tried a Thread but android 4.0 and above doesn't like this because of UI and Threads. What it seems is happening is, gameServerID and gamePositions both have a setTimeOut(1), so both of them will listen for 1 millisecond, this allows for clients to join, and send their position to the server, but doing so SLAMS the server into a slug mode, and positions are sent out to the clients very, very slowly, here is a piece of the logcat output screen from the host
[HIGH]
04-05 02:49:42.093: D/dalvikvm(16836): JIT unchain all for threadid=11
04-05 02:49:42.140: D/dalvikvm(16836): GC_CONCURRENT freed 511K, 59% free 2756K/6663K, external 1657K/2137K, paused 2ms+2ms
04-05 02:49:42.148: W/System.err(16836): java.net.SocketTimeoutException: Try again
04-05 02:49:42.148: W/System.err(16836): at org.apache.harmony.luni.platform.OSNetworkSystem.recv(Native Method)
04-05 02:49:42.152: W/System.err(16836): at dalvik.system.BlockGuard$WrappedNetworkSystem.recv(BlockGuard.java:321)
04-05 02:49:42.156: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:172)
04-05 02:49:42.156: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:181)
04-05 02:49:42.156: W/System.err(16836): at java.net.DatagramSocket.receive(DatagramSocket.java:402)
04-05 02:49:42.160: W/System.err(16836): at com.example.gelorph_v1.gameServer.doInBackground(gameServer.java:139)
04-05 02:49:42.160: W/System.err(16836): at com.example.gelorph_v1.gameServer.doInBackground(gameServer.java:1)
04-05 02:49:42.160: W/System.err(16836): at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-05 02:49:42.160: W/System.err(16836): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-05 02:49:42.160: W/System.err(16836): at java.lang.Thread.run(Thread.java:1019)
04-05 02:49:42.167: W/System.err(16836): java.net.SocketTimeoutException: Try again
04-05 02:49:42.167: W/System.err(16836): at org.apache.harmony.luni.platform.OSNetworkSystem.recv(Native Method)
04-05 02:49:42.167: W/System.err(16836): at dalvik.system.BlockGuard$WrappedNetworkSystem.recv(BlockGuard.java:321)
04-05 02:49:42.171: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:172)
04-05 02:49:42.171: W/System.err(16836): at org.apache.harmony.luni.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:181)
04-05 02:49:42.171: W/System.err(16836): at java.net.DatagramSocket.receive(DatagramSocket.java:402)
[/HIGH]
If anyone could help me fix this last bug, it would be awesome.
Canvas
If you want more snippets of my code just let me know.