At the moment I have a server that will allow clients to connect to it by sending a message "connect", when the server receives this message, it takes in the InetAddress, and then uses that InetAddress to send data to the client, once the client is connected and receives its ID number, it will constantly send data to the UDP socket so it can update its position, now when a new client wants to connect, it will send a message "connect" but only very rarely the new client will connect, What is happening is the client that is already connected is keeping the host.receive function busy, so when the new client goes to connect, it is lucky if the current client connected doesn't jump in the way, and then the client is just left with a blank screen.
What I need help with is, how can I support multiple clients on a UDP socket using the same port?
All clients that will connect to the server are on the same Router,
Here is the whole server code
public class gameServer /*extends Thread*/ extends AsyncTask<String, String, String>{
/**
* Sets up a server for Android applciation
*/
private static final String TAG = "GameServer";
private DatagramSocket socket;
private int port = 50000;
private int players = 0;
private String[] positions = new String[8];
private ArrayList<InetAddress> addresses = new ArrayList();
private boolean wait = false;
private Context contextHolder = null;
//Make an array, this array will hold all the positions
//the clients sent to it,
//using the ID number, it will store it in a array block
//and the "host" can just return it and use that
public gameServer( Context context ) throws IOException
{
//Here we take in the clients block,
//this will be assets[0];
contextHolder = context;
socket = new DatagramSocket( port );
Log.d(TAG, "Server was setup");
}
public DatagramSocket rtnSocket(){ return socket; }
private String getLocalIPAddress()
{
try
{
for (Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); nis.hasMoreElements();)
{
NetworkInterface ni = nis.nextElement();
Log.v(TAG, "NetworkInterface = " + ni.getDisplayName());
for (Enumeration<InetAddress> ips = ni.getInetAddresses(); ips.hasMoreElements();)
{
InetAddress ip = ips.nextElement();
String s = ip.getHostAddress();
Log.v(TAG, "InetAddress = " + s);
if (!ip.isLoopbackAddress())
{
if(InetAddressUtils.isIPv4Address(s)) return s;
}
}
}
}
catch (SocketException e)
{
Log.e(TAG,"getLocalIPAddress()", e);
}
return null;
}
public void getClientPosition(int xPos, int yPos)
{
positions[0] = xPos + ":" + yPos;
}
#Override
protected String doInBackground(String... params) {
InetAddress client = null;
boolean run = true;
String data = "";
DatagramPacket packet = null;
boolean position = false;
while( run )
{
if( data.equalsIgnoreCase( "" ) )
{
}
//Send some data
if( data.equalsIgnoreCase( "connect" ) && wait == true )
{
Log.d(TAG, "Someone wants to connect");
//Increase the total players by 1
players = players + 1;
//Notify to the host (client) something has change
//notify client
//Send a message to the client with the ID
byte[] bufer = new byte[256];
//Send a message "connect" to the host
String msg = Integer.toString( players );
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
//Default ip address of the host
//Take the address from the packet
addresses.add( packet.getAddress() );
Log.d(TAG, "Address is " + addresses.get( addresses.size() - 1 ) );
address = addresses.get( addresses.size() - 1 );
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send packet
try
{
socket.send( p );
}
catch (IOException e)
{
e.printStackTrace();
}
wait = false;
}
if( wait == true && position == true )
{
position = false;
wait = false;
}
for(int i = 0;i < positions.length; i++)
{
if(positions[i] != null)
{
//Log.d(TAG, "X and Y position of asset:"+i+", is:"+ positions[i]);
}
}
//Needs to try and reteive data...
if( wait == false )
{
//Log.d(TAG, "Waiting to retreive data");
byte[] buf = new byte[256];
packet = new DatagramPacket( buf, buf.length );
try
{
socket.receive( packet );
wait = true;
}
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
data = new String( buf, 0, packet.getLength() );
//Log.d(TAG, "Data received from :" + packet.getAddress() + ", holds this value: " + data);
String[] dataStrings = data.split(":");
if( dataStrings[0].equalsIgnoreCase( "position" ) )
{
position = true;
}
}
//Log.d(TAG, "Data received was :" + data);
/*try
{
Thread.sleep( 25 );
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
Log.d(TAG, "Error with trying to sleep");
e.printStackTrace();
}*/
}
Log.d(TAG, "Error with while run value");
return "finished";
}
public int returnPlayers(){ return players; }
}
Here is the Client code
public class gameClient extends AsyncTask<String, String, String>
{
//Variables
private static final String TAG = "gameClient";
private gameServer server;
private boolean rdyForPlay = false;
//Holds all of the over clients blocks
private gameObject[] assets = new gameObject[8];
private int ID = 0;
private int port = 50000;
private Context contextHolder;
//If this client is the host
private boolean host = false;
private DatagramSocket socket = null;
//How many clients are connected to the server
private int totalPlayers = 0;
//Constructor for gameclient
public gameClient( boolean serverTag, Context context )
{
host = serverTag;
//Client is host
if( host == true)
{
host = true;
try
{
//Start the server
contextHolder = context;
server = new gameServer( contextHolder );
this.execute();
}
catch (IOException e)
{
//Error
Log.d(TAG, "Could not start server");
e.printStackTrace();
}
}
//Client is not host
else
{
//Connect to the host
contextHolder = context;
this.execute();
}
}
//Connect to the host, to receive and send data to
public void connectToServer()
{
//Send a connect message to the server
try {
//Create a socket
socket = new DatagramSocket( port );
byte[] bufer = new byte[256];
//Send a message "connect" to the host
String msg = "connect";
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
//Default ip address of the host
address = InetAddress.getByName("192.168.1.59");
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send packet
socket.send( p );
} catch (UnknownHostException e2) {
Log.d(TAG, "Unknown host");
e2.printStackTrace();
} catch (SocketException e) {
Log.d(TAG, "Socket problem");
e.printStackTrace();
} catch (IOException e) {
Log.d(TAG, "I/O problem");
e.printStackTrace();
}
//Receive the message back
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket( buf, buf.length );
//Try to receive a packet from the server
try
{
Log.d(TAG, "Waiting for data");
socket.receive( packet );
}
//Error
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
//Convert the packet to a string
String data = new String( buf, 0, packet.getLength() );
//Use the string to find out what ID this client is
ID = Integer.parseInt( data );
//Setup the client game
setUpClient();
}
//Setup the client game/screen
public void setUpClient()
{
//Setup the client using the ID that was given by the host
Log.d(TAG, "ID is : " + ID);
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.player), 250, 300);
assets[ID] = temp;
for(int i = 0; i < ID; i++)
{
temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 50*i, 50*i);
assets[i] = temp;
}
//If this client is the host, then pass the client to the server for easy access
if( host == true )
{
server.getClientPosition( assets[ID].returnPosX(), assets[ID].returnPosY() );
}
}
//When the screen is touched
public void sendTouchEvent(float xSet, float ySet)
{
assets[ID].setPosition( xSet, ySet );
}
#Override
//Keep the game updated
protected String doInBackground(String... params)
{
//Connect to the server
if( host == false ){ while(ID == 0) { Log.d( TAG, "Client will connect to server" ); connectToServer(); } }
//If the client is host, then start the server thread
if( host == true ) { setUpClient(); server.execute(); }
//game us now ready to be played
rdyForPlay = true;
boolean run = true;
boolean setupPlayer = false;
while( run )
{
int players = 0;
//Tell the server to give position of players
//if( setupPlayer == true )
//{
// setUpClient();
// setupPlayer = false;
//}
if( host == true )
{
server.getClientPosition( assets[ID].returnPosX(), assets[ID].returnPosY() );
int newPlayers = server.returnPlayers();
if( players != newPlayers )
{
for(int i = players; i < newPlayers; i++)
{
i = i+1;
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 50*i, 50*i);
assets[i] = temp;
}
players = newPlayers;
}
}
//If this is a client then do this
if( host == false )
{
try {
//If the socket is not yet setup, set it up
if(socket == null)
{
socket = new DatagramSocket( port );
}
byte[] bufer = new byte[256];
//Using the ID given at the start, send X and Y position to the server
String msg = "position:" + ID +":"+ assets[ID].returnPosX() +":"+ assets[ID].returnPosY();
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
address = InetAddress.getByName("192.168.1.59");
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send the data
socket.send( p );
Log.d(TAG, "data sent");
} catch (UnknownHostException e2) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with unknown host");
e2.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with socket");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with sending/receiving data");
e.printStackTrace();
}
}
//Host data will ofcourse be differnet
}
Log.d(TAG, "Error with run value");
return "finished";
}
//If a new player needs to be added to the array
private void newPlayer( int idOfNewPlayer )
{
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 250, 300);
assets[ idOfNewPlayer ] = temp;
}
//Update all the assets in the game
private void updateAssets()
{
}
//Return methods
public gameObject[] rtnAssets(){ return assets; }
public int rtnID(){ return ID; }
public boolean rtnRdy(){ return rdyForPlay; }
public gameServer rtnServer(){ return server; }
public boolean rtnHost(){ return host; }
//Stop the client server if host
public void stopServers()
{
if( host == true )
{
socket.close();
server.rtnSocket().close();
System.gc();
}
}
public void stopBackground()
{
socket.close();
this.cancel( true );
System.gc();
}
}
Wheneva we request for a connection we'll kwn of one port number and request. So, try to keep that port free. It can be done by using the other ports in ur system which are free. So when a client requests for connection reply back with a port number and assign that client with that port number. Our system can support upto 10k connection due to so many logical ports. So I assume it shouldnt be a problem for many users.
And once connection is established, user will communicate on the port it is assigned to and thus other users can access ur server easily.
Related
I'm trying to make a program that has a client, and intermediate host and a server. The client sends a packet to the host, the host sends it to the server and than the server sends a packet back to the host who sends it to the client. This should repeat 11 times.
Here is my code:
public class SimpleEchoClient {
DatagramPacket sendPacket, receivePacket;
DatagramSocket sendReceiveSocket;
public SimpleEchoClient()
{
try {
sendReceiveSocket = new DatagramSocket();
} catch (SocketException se) { // Can't create the socket.
se.printStackTrace();
System.exit(1);
}
}
public byte[] createWriteByte() {
byte[] msg = new byte[100];
int position = 2;
Path path = Paths.get("test.txt");
String fileName = path.getFileName().toString();
//In datagrampackets, our data needs to be converted into bytes
msg = new byte[100];
msg[0] = 0x00;
msg[1] = 0x02;
for(int i=0; i<fileName.getBytes().length; i++) {
msg[position] = fileName.getBytes()[i];
position++;
}
msg[position] = 0x00;
String mode = "netascii";
position++;
for(int i = 0; i < mode.getBytes().length; i++) {
msg[position] = mode.getBytes()[i];
position++;
}
msg[position] = 0;
return msg;
}
public byte[] createReadByte() {
byte[] msg = new byte[100];
int position = 2;
Path path = Paths.get("test.txt");
String fileName = path.getFileName().toString();
//In datagrampackets, our data needs to be converted into bytes
msg = new byte[100];
msg[0] = 0x00;
msg[1] = 0x01;
for(int i=0; i<fileName.getBytes().length; i++) {
msg[position] = fileName.getBytes()[i];
position++;
}
msg[position] = 0x00;
String mode = "netascii";
position++;
for(int i = 0; i < mode.getBytes().length; i++) {
msg[position] = mode.getBytes()[i];
position++;
}
msg[position] = 0;
return msg;
}
public void sendAndReceive(boolean checkRead)
{
Path path = Paths.get("test.txt");
String fileName = path.getFileName().toString();
//In datagrampackets, our data needs to be converted into bytes
byte[] msg;
if(checkRead) {
msg = createReadByte();
checkRead = false;
}else{
msg = createWriteByte();
checkRead = true;
}
String str = new String(msg);
System.out.println(str);
System.out.println("Hello");
System.out.println(msg);
try {
sendPacket = new DatagramPacket(msg, msg.length,
InetAddress.getLocalHost(), 5000);
} catch (UnknownHostException e) {
e.printStackTrace();
System.exit(1);
}
try {
sendReceiveSocket.send(sendPacket);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
sendReceiveSocket.close();
try {
Thread.sleep(5000);
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
System.out.println("Client: Packet sent.\n");
//NOW TO RECEIVE THE DATA
DatagramSocket receiveSocket = null;
try {
receiveSocket = new DatagramSocket(5000);
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte data[] = new byte[4];
receivePacket = new DatagramPacket(data, data.length);
try {
// Block until a datagram is received via sendReceiveSocket.
receiveSocket.receive(receivePacket);
} catch(IOException e) {
e.printStackTrace();
System.exit(1);
}
// Process the received datagram.
for(int j =0; j < data.length; j++) {
System.out.println(data[j] & 0xff);
}
// We're finished, so close the socket.
sendReceiveSocket.close();
}
public static void main(String args[])
{
boolean checkRead = true;
int count =0;
for(int i = 0; i<10; i++) {
System.out.println("Count:" + count);
SimpleEchoClient c = new SimpleEchoClient();
c.sendAndReceive(checkRead);
}
}
}
public class IntermediateHost {
DatagramSocket receiveFromClient, receiveFromServer;
DatagramPacket receiveClientPack, sendClientPacket, receiveServerPacket, sendServerPacket;
public IntermediateHost() {
try {
receiveFromClient = new DatagramSocket(5000);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void receiveAndEcho() {
byte [] b = new byte[100];
//When we receive the packet we need to store it in a datagrampacket which is initally empty
receiveClientPack = new DatagramPacket(b, b.length);
InetAddress ip = null;
try {
receiveFromClient.receive(receiveClientPack);
ip = InetAddress.getByName("localhost");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String message = new String(b);
System.out.println(message);
System.out.println(b);
int port = 3001;
sendClientPacket = new DatagramPacket(b, b.length, ip, port);
try {
receiveFromClient.send(sendClientPacket);
} catch (IOException e1) {
e1.printStackTrace();
}
receiveFromClient.close();
//SEND BACK TO THE CLIENT
try {
Thread.sleep(5000);
receiveFromServer = new DatagramSocket(3001);
} catch (InterruptedException | SocketException e1) {
e1.printStackTrace();
}
byte [] b1 = new byte[4];
//When we receive the packet we need to store it in a datagrampacket which is initally empty
receiveServerPacket = new DatagramPacket(b1, b1.length);
//This method will wait for the incoming packet and it will copy all values from that packet
//into receiveClientPack..so at this point the byte array will not be empty
try{
receiveFromServer.receive(receiveServerPacket);
}catch (Exception e) {
System.out.println(e);
}
for(int i =0;i < b1.length; i++) {
System.out.println(b1[i] & 0xff);
}
InetAddress ip1 = null;
try {
ip1 = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
int port1 = 5000;
sendServerPacket = new DatagramPacket(b1, b1.length, ip1, port1);
try {
receiveFromServer.send(sendServerPacket);
} catch (IOException e) {
e.printStackTrace();
}
receiveFromServer.close();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws IOException, InterruptedException {
while(true) {
IntermediateHost inter = new IntermediateHost();
inter.receiveAndEcho();
}
}
}
public class SimpleEchoServer {
DatagramPacket sendPacket, receivePacket;
DatagramSocket sendSocket, receiveSocket;
public SimpleEchoServer()
{
try {
sendSocket = new DatagramSocket();
receiveSocket = new DatagramSocket(3001);
} catch (SocketException se) {
se.printStackTrace();
System.exit(1);
}
}
public byte[] sendBackRead() {
byte [] bytesToSend = new byte[4];
bytesToSend[0] = 0x00;
bytesToSend[1] = 0x03;
bytesToSend[2] = 0x00;
bytesToSend[3] = 0x01;
return bytesToSend;
}
public byte[] sendBackWrite() {
byte [] bytesToSend = new byte[4];
bytesToSend[0] = 0x00;
bytesToSend[1] = 0x04;
bytesToSend[2] = 0x00;
bytesToSend[3] = 0x00;
return bytesToSend;
}
public boolean checkRead(byte[] msg) {
if(msg[1] == 1) {
return true;
}
return false;
}
public boolean checkWrite(byte[] msg) {
if(msg[1] == 2) {
return true;
}
return false;
}
public void receiveAndEcho() throws UnknownHostException
{
byte data[] = new byte[100];
receivePacket = new DatagramPacket(data, data.length);
System.out.println("Server: Waiting for Packet.\n");
try {
System.out.println("Waiting..."); // so we know we're waiting
receiveSocket.receive(receivePacket);
} catch (IOException e) {
System.out.print("IO Exception: likely:");
System.out.println("Receive Socket Timed Out.\n" + e);
e.printStackTrace();
System.exit(1);
}
boolean checkRead = checkRead(data);
boolean checkWrite = checkWrite(data);
String message = new String(data);
System.out.println(message);
receiveSocket.close();
// Slow things down (wait 5 seconds)
try {
Thread.sleep(5000);
} catch (InterruptedException e ) {
e.printStackTrace();
System.exit(1);
}
byte[] bytesToSend = null;
System.out.println(data[1]);
if(checkRead) {
bytesToSend = sendBackWrite();
}else if(checkWrite) {
bytesToSend = sendBackRead();
}
for(int i =0;i < bytesToSend.length; i++) {
System.out.println(bytesToSend[i] & 0xff);
}
InetAddress ip = InetAddress.getLocalHost();
sendPacket = new DatagramPacket(bytesToSend, bytesToSend.length,
ip, 3001);
// Send the datagram packet to the client via the send socket.
try {
sendSocket.send(sendPacket);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
System.out.println("Server: packet sent");
// We're finished, so close the sockets.
sendSocket.close();
receiveSocket.close();
}
public static void main( String args[] ) throws UnknownHostException
{
while(true) {
SimpleEchoServer c = new SimpleEchoServer();
c.receiveAndEcho();
}
}
}
Now this code works if I were to only send one packet to the host, which sends to the server which returns another packet to the client from the host. However when I try to send more than one packet I get an error. To send more than one packet I basically create a loop in the main that simply calls the methods 11 times and i place a while loop in the server and host to have it running continuously in order to wait for packets. To see it run once, just eliminate the while loops in the main function of all three classes.
Any help as to how I can fix this error is greatly appreciated! Thanks!
On each call to the SimpleEchoClient c = new SimpleEchoClient();, your code tries to create a client on port 5000. Since you already have a client running on the same port, the exception is thrown.
So do it only once and send the packet 11 times.
public static void main(String args[])
{
boolean checkRead = true;
int count =0;
SimpleEchoClient c = new SimpleEchoClient();
for(int i = 0; i<=10; i++) {
System.out.println("Count:" + count);
c.sendAndReceive(checkRead);
}
}
Check how I have changed the loop condition to <=10 to make sure that 11 packets are sent.
I have written an app which receives multicast packets sent by a sender (containing audio).
I have used Netty 4 and have got the app working on Windows but it will not receive multicast packets when run on Linux (Debian Wheezy (raspi) and Ubuntu 12).
I have created some test code that can send and receive multicast packets, the results are:
Send Windows to Windows works.
Send Linux to Windows works.
Send Windows to Linux, packets are sent but not received.
I run the app as root and have SO_BROADCAST set to true.
What have I missed?
If I use the standard Java MulticastSocket instead of Netty, then the app works, but I would prefer to use Netty as it is easy to use and simplifies to code greatly.
The test code is :
public class TestMulticast {
private int port = 51972;
private Logger log = Logger.getLogger(this.getClass());
private InetAddress remoteInetAddr = null;
private InetSocketAddress remoteInetSocket = null;
private InetAddress localInetAddr = null;
private InetSocketAddress localInetSocket = null;
private DatagramChannel ch = null;
private EventLoopGroup group = new NioEventLoopGroup();
private boolean bSend = false;
public TestMulticast(String localAddress, String remoteAddress, String sPort, boolean bSend) {
this.bSend = bSend;
try {
localInetAddr = InetAddress.getByName(localAddress.trim());
remoteInetAddr = InetAddress.getByName(remoteAddress.trim());
} catch (Exception e) {
log.error("Error creating InetAddresses. Local: " + localAddress + " Remote: " + remoteAddress, e);
}
try {
port = Integer.parseInt(sPort);
} catch (Exception e) {
log.error("Error Parsing Port: " + sPort, e);
}
}
public void run() throws Exception {
log.debug("Run TestMulticast, Send Packet = " + bSend);
try {
localInetSocket = new InetSocketAddress(port);
remoteInetSocket = new InetSocketAddress(remoteInetAddr, port);
Bootstrap b = new Bootstrap();
b.group(group);
b.channelFactory(new ChannelFactory<Channel>() {
#Override
public Channel newChannel() {
return new NioDatagramChannel(InternetProtocolFamily.IPv4);
}
});
b.option(ChannelOption.SO_BROADCAST, true);
b.option(ChannelOption.SO_REUSEADDR, true);
b.option(ChannelOption.IP_MULTICAST_LOOP_DISABLED, false);
b.option(ChannelOption.SO_RCVBUF, 2048);
b.option(ChannelOption.IP_MULTICAST_TTL, 255);
b.handler(new LoggingHandler(LogLevel.DEBUG));
log.debug("Am I Logged on as ROOT: " + PlatformDependent.isRoot());
ch = (DatagramChannel) b.bind(localInetSocket).sync().channel();
log.debug("Result of BIND: " + ch.toString());
if (remoteInetAddr.isMulticastAddress()) {
NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr);
ChannelFuture future = ch.joinGroup(remoteInetSocket, nic);
log.debug("Result of Join: " + future.toString());
} else {
log.debug("############NOT A MULTICAST ADDRESS: '" + remoteInetAddr.getHostAddress() + "'");
}
if (bSend) {
group.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
Date date = new Date();
byte[] bytes = date.toString().getBytes();
ByteBuf buffer = Unpooled.copiedBuffer(bytes);
DatagramPacket packet = new DatagramPacket(buffer, remoteInetSocket, localInetSocket);
ch.writeAndFlush(packet);
} catch (Exception e) {
log.error("Error Sending DatagramPacket", e);
}
}
}, 0, 10, TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error(e);
}
}
public void stop() {
try {
if (ch != null) {
try {
ch.close();
} catch (Exception e) {
log.error("Error Closing Channel", e);
}
}
group.shutdownGracefully();
} catch (Exception e) {
log.error("Error ShuutingDown", e);
}
}
}
EDIT:
If found my problem, I should learn to read the docs!!
For Mutlicast you should bind to the WILDCARD Address.
So changing the code to
localInetSocket = new InetSocketAddress(remotePort);
....
ch = (DatagramChannel) b.bind(localInetSocket).sync().channel();
....
if (remoteInetAddr.isMulticastAddress()) {
NetworkInterface nic = NetworkInterface.getByInetAddress(localInetAddr);
ChannelFuture future = ch.joinGroup(remoteInetSocket, nic);
log.debug("Result of Join: " + future.toString());
}
I've modified the full code above with the new changes..
Pete.
I'm trying to send over a small packet from one device to another,
My device ip is 192.168.1.59 which is the host,
Here is my server code
public class gameServer extends Thread{
/**
* Sets up a server for Android applciation
*/
private static final String TAG = "GameServer";
private DatagramSocket socket;
private int port = 50000;
private InetAddress local = null;
public gameServer( ) throws IOException
{
socket = new DatagramSocket( port );
Log.d(TAG, "Server was setup");
}
private String getLocalIPAddress()
{
try
{
for (Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); nis.hasMoreElements();)
{
NetworkInterface ni = nis.nextElement();
Log.v(TAG, "NetworkInterface = " + ni.getDisplayName());
for (Enumeration<InetAddress> ips = ni.getInetAddresses(); ips.hasMoreElements();)
{
InetAddress ip = ips.nextElement();
String s = ip.getHostAddress();
Log.v(TAG, "InetAddress = " + s);
if (!ip.isLoopbackAddress())
{
if(InetAddressUtils.isIPv4Address(s)) return s;
}
}
}
}
catch (SocketException e)
{
Log.e(TAG,"getLocalIPAddress()", e);
}
return null;
}
public void passClient( gameObject clientTemp )
{
}
#Override
public void run()
{
Log.d(TAG, "Ip address used:" + getLocalIPAddress() );
while( true )
{
//Send some data
try
{
local = InetAddress.getByName("127.0.0.1");
}
catch (UnknownHostException e2) {
e2.printStackTrace();
}
String msg = "hello there";
int msgLength = msg.length();
byte[] message = msg.getBytes();
DatagramPacket p = new DatagramPacket( message, msgLength, local, port );
try
{
socket.send( p );
}
catch (IOException e2)
{
Log.d(TAG, "Error with sending");
e2.printStackTrace();
}
}
}
}
Here is my client
public class gameClient extends Thread {
private static final String TAG = "gameClient";
private gameServer server;
private boolean rdyForPlay = false;
private ArrayList<gameObject> assets = new ArrayList();
private int ID = 0;
private maths cal = new maths();
public gameClient( boolean serverTag )
{
if( serverTag == true)
{
try
{
server = new gameServer();
server.run();
}
catch (IOException e)
{
Log.d(TAG, "Could not start server");
e.printStackTrace();
}
}
else
{
//DELETE!!!
//ONLY FOR TESTING
DatagramSocket socket = null;;
try
{
socket = new DatagramSocket( 50000 );
}
catch (SocketException e1)
{
e1.printStackTrace();
}
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket( buf, buf.length );
try
{
socket.receive( packet );
}
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
String data = new String( buf, 0, packet.getLength() );
Log.d(TAG, "Data received was :" + data);
}
}
public void sendTouchEvent(float xSet, float ySet)
{
}
#Override
public void run()
{
}
private void updateAssets()
{
}
}
When the code tries to receive a packet it just crashs on the socjet.receive( packet );
can anyone see any reason why?
Canvas
Your problem is that you have two try blocks. If the first one catches something socket stays null. So do something like that:
DatagramSocket socket = null;
try
{
socket = new DatagramSocket( 50000 );
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket( buf, buf.length );
socket.receive( packet );
}
catch (SocketException e1)
{
e1.printStackTrace();
}
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
Make sure to close() the socket onDestroy of your Activity!
Also consider AutoDiscovery instead of static IP's: AutoDiscovery
I am doing some testing with SCTP in a simple client server model.
My Server code is following:
public class SCTPServer extends Thread {
InetSocketAddress serverSocketAddress=null;
SctpServerChannel sctpServerChannel;
SctpChannel sctpChannel;
boolean running = false;
ByteBuffer bf = ByteBuffer.allocateDirect(160);
String id= null;
public SCTPClient sctpClient= null;
public SCTPServer(String IP, int port, String clientIp, int clientPort, String id) {
try {
serverSocketAddress = new InetSocketAddress(IP, port);
sctpServerChannel = SctpServerChannel.open().bind(serverSocketAddress);
} catch (Exception e) {
System.out.println("Failed to open Sctp connection Reciver on IP:" + IP + " and Port:" + port+" "+e);
System.exit(0);
}
}
public void run()
{
running = true;
while (running) {
try {
sctpClient.sendAsp();
sctpChannel = sctpServerChannel.accept();
try {
sctpChannel.receive(bf, null, null);
bf.flip();
byte[] barry = new byte[bf.limit()]; //we may keep the received data on this new byte arrray here or in some
bf.get(barry, 0, bf.limit());
bf.clear();
System.out.println("new sctp message is received");
System.out.println(new String(barry));
} catch (IOException ex) {
System.out.println("Failed to receive from sctp Channel " + ex);
}
} catch (Exception ex) {
System.out.println("Exception at Starting SCTP Server channel"+ ex);
}
}
}
}
and the client code following:
public class SCTPClient extends Thread {
SctpChannel sctpChannel;
InetSocketAddress socketAddress;//= new InetSocketAddress("202.51.176.44", 5555);
boolean runniung = false;
ByteBuffer bf = ByteBuffer.allocateDirect(160);
String id= null;
public SCTPClient(String ip, int port, int maxInStream, int maxOutStream, String id) {
socketAddress = new InetSocketAddress(ip, port);
this.id = id;
//InetSocketAddress sockAd = new InetSocketAddress("202.51.176.44",55556);
try {
sctpChannel = SctpChannel.open();
System.out.println("SCTP connection opened with IP==" + ip + " port == " + port);
//sctpChannel.bind(sockAd);
sctpChannel.connect(socketAddress, maxInStream, maxOutStream);
runniung = true;
sendMSG();
} catch (Exception ex) {
System.out.println("Exception at opening sctp connection:" + ex);
System.exit(0);
}
}
public void sendMSG()
{
MessageInfo messageInfo =null;
/*try {
} catch (IOException ex) {
System.out.println("Failed to create Message Info " + ex.toString());
}*/
messageInfo = MessageInfo.createOutgoing( null, 0);
ByteBuffer byteBuffer = buildMessage(1, "test");
try {
sctpChannel.send(byteBuffer, messageInfo);
byteBuffer.clear();
System.out.println("A message has been sent");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Failed to send the message due to :" + e.toString());
}
}
public static ByteBuffer buildMessage(Integer id,String infoString)
{
//We can calculate the total length of the message hard codedly, even before building the total message.
int totalLength = (id!=null) ? 16 : 8;
totalLength += (infoString!=null) ? (4+infoString.length()) : 0;
ByteBuffer data = ByteBuffer.allocateDirect(totalLength);
//Own part of ASP Up message
if(id!=null)
{
data.putInt(ASPIdentifier);
}
if(infoString!=null)
{
data.put(infoString.getBytes());
}
return data;
}
}
The problem here is that, when I try to connect to a remote PC the SCTP association is established successfully. But when the SendMSG function is called the system aborts with following exception
java.net.SocketException: Invalid argument
at sun.nio.ch.SctpChannelImpl.send0(Native Method) Failed to send the message due to :java.net.SocketException: Invalid argument
at sun.nio.ch.SctpChannelImpl.sendFromNativeBuffer(SctpChannelImpl.java:1027)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:987)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:967)
at sctptester.SCTPClient.sendMSG(SCTPClient.java:79)
at sctptester.SCTPClient.<init>(SCTPClient.java:40)
at test.main(test.java:66)
After comparing your client code to a simulator that I just wrote last week, I can see only one real difference. You did not bind your client's socket to a local InetSocketAddress. Where you have:
sctpChannel.bind(sockAd);
You need to put something like:
InetSocketAddress localISA = new InetSocketAddress(localIPAddress, localPort);
sctpChannel.bind(localISA);
I believe this will do it for you, or at least get you past the error you posted.
I think you should add the destination when sending in the client,
messageInfo = MessageInfo.createOutgoing( null, 0);
//replace with
msgInfo = MessageInfo.createOutgoing(new InetSocketAddress(ip, port), 0);
I, doing some computer network homework and I have to develop some sort of distributed DBMS which are connected to each other with peer to peer network, so I have a TCP client and a TCP server in one .java file which running next to each other by threads. the TCP Server of the class always listen to the other TCP client from others and give them service, the problem is when I System.out the String which I have to send back to the client on the Server side it's in the way which it's supposed to be but after sending , the client gets nothing and prints null. I wrote my code based on tutorials I found on the net and I when I test them they worked well but it's not working in my own code. could you see where my problem is? thanks
class CommandComp
{
int PORT = 1210;
int PORT2 = 1211;
String IPLocal = "";
String IPdest = "";
InetAddress IPAD;
InetAddress IPAD2;
int numOfNodes;
int numOfNodesnonchanged;
String[] Nodes;
Random rand = new Random();
int max = 2000;
int min = 1000;
String command;
Socket clientSocket;
CommandComp(String[] IPdest, String IPLocal, int numOfNodes, String command)
{
try
{
this.numOfNodes = numOfNodes;
numOfNodesnonchanged = numOfNodes;
this.IPLocal = IPLocal;
this.Nodes = IPdest;
this.command = command;
// this.IPAD = InetAddress.getByName(this.IPdest);
this.IPAD2 = InetAddress.getByName(this.IPLocal);
// clientSocket = new Socket(this.IPAD , PORT ,this.IPAD2 , PORT2 );
}
catch (Exception e)
{
// //e.printStackTrace();
}
}
public String call()
{
int i = 0;
while (numOfNodes > 0)
{
String response = "";
try
{
Thread.sleep(rand.nextInt(max - min + 1) + min);
i = numOfNodes - 1;
int max2 = 50;
int min2 = 10;
this.IPAD = InetAddress.getByName(Nodes[i]);
clientSocket = new Socket(this.IPAD, PORT, this.IPAD2, PORT2 + rand.nextInt(max2 - min2 + 1) + min2);
PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.println(command);
System.out.println(inFromServer.readLine());
response = inFromServer.readLine();
outToServer.close();
inFromServer.close();
clientSocket.close();
numOfNodes--;
System.out.println(Nodes[i] + " Remote DBMS");
System.out.println(response);
}
catch (Exception e)
{
e.printStackTrace();
try
{
clientSocket.close();
}
catch (Exception e2)
{
// TODO: handle exception
}
}
}
return command;
}
}
class TCPListnerService
implements Callable<Object>
{
String from;
String to;
ServerSocket Server;
String IP = "";
int numOfNodes;
int numofNodesUnchanged;
static clientThread t[];
TCPListnerService(String IP, int numOfNodes)
{
try
{
this.IP = IP;
this.numOfNodes = numOfNodes;
numofNodesUnchanged = numOfNodes * 2;
this.t = new clientThread[numofNodesUnchanged];
InetAddress IPAD = InetAddress.getByName(IP);
Server = new ServerSocket(1210, 20, IPAD);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String call()
throws Exception
{
String gotten = "";
while (numOfNodes > 0)
{
Socket connected = Server.accept();
for (int i = 0; i < numofNodesUnchanged; i++)
{
if (t[i] == null)
{
(t[i] = new clientThread(connected)).start();
break;
}
}
}
return gotten;
}
}
class clientThread
extends Thread
{
Socket clientSocket = null;
sqlite DB = new sqlite();
String response = "";
String fromclient;
String delims = "[ =)(',\n\t\r]+";
String[] tokens;
public clientThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run()
{
try
{
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter outToClient = new PrintWriter(clientSocket.getOutputStream(), true);
fromclient = inFromClient.readLine();
tokens = fromclient.split(delims);
if (tokens[0].equalsIgnoreCase("create")
|| tokens[0].equalsIgnoreCase("drop")
|| tokens[0].equalsIgnoreCase("delete")
|| tokens[0].equalsIgnoreCase("insert")
|| tokens[0].equalsIgnoreCase("update")
|| tokens[0].equalsIgnoreCase("select"))
{
response = DB.RunQuery(fromclient);
System.out.println(response);
outToClient.print(response);
clientS.close();
}
else if (tokens[0].equalsIgnoreCase("shut"))
{
System.exit(0);
}
inFromClient.close();
outToClient.close();
clientSocket.close();
}
catch (Exception e)
{
}
;
}
}
The problem is here:
inFromClient.close();
outToClient.close();
clientSocket.close();
You are closing (1) the input stream, which closes the socket, (2) the PrintWriter, which flushes it and closes the socket, and (3) the socket. Obviously (2) cannot succeed if the socket is already closed. The data you sent to the client is still buffered, never got flushed, so it never got sent.
Just close the PrintWriter, and close the socket in a finally block in case (2) fails somehow. No need to close the input at all.