Sign in to follow this  
PhlashStudios

Polling for other Computers on a LAN in Java

Recommended Posts

PhlashStudios    122
Ok so for this program I'm writing, I want to poll all the other computers that are connected to the same network as I am. Right now I'm using a for loop to just take my i.p address and go through each different possible local variation and try to connect to it and get a list of the computers on the network that way (the ones that are running my program ne way). This method seems sort of brute force though and is pretty slow. Is there a better way to do this? (I know how to do this using DirectPlay in c++ so it can be done...just not sure how) Thanks in advance

Share this post


Link to post
Share on other sites
Wolfdog    268
I have no experience with networking in Java, but in general what you need is broadcasting. Basicly you setup each machine to listen on the same address (the broadcast address). When your client machine then asks for all other machines it sends out the broadcast packet. When the other machines read the packet they can respond accordingly. A small link http://en.wikipedia.org/wiki/Broadcast_address.

Share this post


Link to post
Share on other sites
Ezzaral    122
Is there any reason that your remote clients can't register with a central controller when they are invoked? That would seem the easiest to me. If they registered their availabilty, you wouldn't have to go hunting blind for them.

Share this post


Link to post
Share on other sites
PhlashStudios    122
Well the whole thing about this is not having a centralized server...the broadcast address seems really good I'm just not sure how to get a server to listen to another address like 192.168.1.64.255 or something.
So far i have this code:

public class BroadcastRunnable implements Runnable{
public void run(){
int port = 5000;
try{
System.out.println("Starting server on port: " + port);
ServerSocket socket = new ServerSocket();
SocketAddress adr = socket.getLocalSocketAddress();
//I just dont know how to stick the extra .255 on there
socket.bind(adr);

while (true) {

}
}catch(Exception ex){ex.printStackTrace();}
}
}

/

Share this post


Link to post
Share on other sites
Wolfdog    268
You dont want to add .255 to the end of the address. You want to get the bitwise or result of your ip address and the bit complement of your subnet mask(basicly the inverse). So if your subnet mask is 255.255.255.0 you want 0.0.0.255 (setting every 1 bit to 0 and every 0 bit to 1). Then you or the address 192.168.1.64 | 0.0.0.255 will give you 192.168.1.255 this is your broadcast address. In most cases to send/recv on the broadcast address you need to use specific functions because that address is reserved for broadcast only. You may want to browse around any documentation, there might be functions to handle all of this for you.

Share this post


Link to post
Share on other sites
rip-off    10976
You can't broadcast TCP traffic, TCP is a point to point protocol. Instead, create a DatagramSocket to listen at a given port. Have clients create a DatagramSocket and send a DatagramPacket (or whatever the class is) to the broadcast address. I think the address 255.255.255.255 will work. See the note from the DatagramSocket documentation page:
Quote:

UDP broadcasts sends are always enabled on a DatagramSocket. In order to receive broadcast packets a DatagramSocket should be bound to the wildcard address. In some implementations, broadcast packets may also be received when a DatagramSocket is bound to a more specific address.

Example: DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888)); Which is equivalent to: DatagramSocket s = new DatagramSocket(8888); Both cases will create a DatagramSocket able to receive broadcasts on UDP port 8888.


Clients send their packet and listen for responses. Add response packet InetAddresses to a list and then attempt to initiate your TCP connection to it. (ServerSockets are TCP... right? [smile] )

Share this post


Link to post
Share on other sites
Antheus    2409
Quote:
Original post by PhlashStudios
What if the ip i get is incomplete?


Incomplete?

Server will receive DatagramPacket. That one has getSocketAddress(), which is where you respond to.

Share this post


Link to post
Share on other sites
rip-off    10976
Quote:
Original post by PhlashStudios
Ok so i set the address of the DatagramPacket to 255.255.255.255 and send it there on port 8888 and that should work?


Yes, all hosts in the same LAN segment listening on UDP port 8888 should hear the packet.

Share this post


Link to post
Share on other sites
rip-off    10976
Here is a similar program I have used before (client version). The server was written in C++, but all it did was create a UDP socket (java DatagramSocket) and every time someone sent it a packet (java DatagramPacket )it just got the address of the sender and echoed "Server name = whatever" back at them.

Here is the client source (includes a stupid GUI, written hastily, don't blame me [smile] )


import java.io.IOException;
import java.net.InetAddress;
import java.net.*;
import java.net.UnknownHostException;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

public class ServerQuery
{
private static final int QUERY_PORT = 1234;//13457;
InetAddress address = null;
DatagramSocket socket = null;
//DatagramPacket packet;
JTextArea messageArea;

ServerQuery()
{
//DatagramPacket packet;
JFrame frame = new JFrame("ServerQuery");
messageArea = new JTextArea("Servers:\n");
messageArea.setSize(300,300);
messageArea.setEditable( false );
frame.setSize(300,300);
Container pane = frame.getContentPane();
pane.setLayout( new BorderLayout() );
pane.add( new JScrollPane(messageArea), BorderLayout.CENTER );

JButton button = new JButton("refresh");
button.addActionListener(
new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
refresh();
}
}
);
pane.add( button, BorderLayout.SOUTH );
frame.setVisible( true );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);

try
{
//address = InetAddress.getByAddress(ip);
socket = new DatagramSocket();
socket.setBroadcast( true );
refresh();
}
catch( SecurityException e )
{
print( e.toString() );
}
catch( IOException e )
{
print( e.toString() );
}
}

public static void main( String[] args )
{
ServerQuery query = new ServerQuery();
query.run();
}

public void print( String msg )
{
messageArea.setText( messageArea.getText() + '\n' + msg );
}

private void refresh()
{
messageArea.setText("Servers:\n");
try
{

byte []ip = new byte[4];
for( int i = 0 ; i < 4; ++i )
{
ip[i] = (byte)255;
}
address = InetAddress.getByAddress(ip);
String meaningless = "hi server how are you??? im grand thanks just tell us your ip, no?";
meaningless += '\0';
DatagramPacket packet = new DatagramPacket( meaningless.getBytes(), meaningless.length() );
packet.setPort( QUERY_PORT );
packet.setAddress( address );
socket.send( packet );
}
catch( UnknownHostException e )
{
print( e.toString() );
}
catch( SecurityException e )
{
print( e.toString() );
}
catch( IOException e )
{
print( e.toString() );
}
}

public void run()
{
while(true)
{
try
{
byte [] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
socket.receive( packet );

int indexOfNul = 0;
while( bytes[indexOfNul] != 0 )
{
indexOfNul++;
}
print( new String( packet.getData(),0,indexOfNul ) );
print( "Server at address : " + packet.getAddress().toString() );
}
catch( IOException e )
{
print( e.toString() );
}
}
}
}





Here is a simple echo server I wrote for some reason ( I think it was to test UDP through a firewall or some stupid reason ). Note the port is different.


import java.net.*;

class Echo
{
private static final int SIZE = 1024;
public static void main( String [] args )
{
System.out.println("UDP echo server running...");
try
{
byte [] data = new byte[SIZE];
DatagramPacket packet = new DatagramPacket(data,SIZE);
DatagramSocket socket = new DatagramSocket(1234);//24567);
while(true)
{
try
{
socket.receive( packet );
String string = new String( packet.getData(),0 , packet.getLength() );
System.out.println( java.util.Calendar.getInstance().getTime().toString() + ": Echoing message from " + packet.getAddress().toString() + ':' + packet.getPort() + " " + string );
packet.setAddress( packet.getAddress() );
socket.send( packet );
}
catch( Exception e )
{
System.out.println(e);
}
}
}
catch( Exception e )
{
System.out.println(e);
}
}

}





You can try that (it may need a tiny but of work, this was old, throw away code).

As for your question as to how to get the broadcast address, this is the way I seem to have chosen:

byte []ip = new byte[4];
for( int i = 0 ; i < 4; ++i )
{
ip[i] = (byte)255;
}
address = InetAddress.getByAddress(ip);




Im sure there are easier ways, like this probably:

address = InetAddress.getByName("255.255.255.255");


Share this post


Link to post
Share on other sites
Ezzaral    122
You can mask the address like so:
InetAddress address = InetAddress.getByName("192.168.0.1");
byte[] addrBytes= address.getAddress();
addrBytes[3]=(byte)255;
InetAddress newAddress = InetAddress.getByAddress(addrBytes);

Share this post


Link to post
Share on other sites

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