I'm writing an Android app to communicate with a Windows service over socket connections.
The code is working but I want to add the ability to detect devices connected on local network so the app can determine which computer is running the windows service I want, I'm using the code below which I got from this website too. My issue is the code below only detects android devices and doesn't detect my laptop. I can ping my device from my laptop and ping my laptop from my device, so what to do from here?
public void checkHosts(String subnet) {
int timeout = 1000;
for (int i = 1; i < 254; i++) {
String host = subnet + "." + i;
try {
if (InetAddress.getByName(host).isReachable(timeout)) {
System.out.println(host + " is reachable");
System.out.println("Host Name: "
+ InetAddress.getByName(host).getHostName());
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
InetAddress.isReachable() is not very reliable.
If ICMP messages are blocked you won't get an answer.
What you could do is sending a broadcast message.
Your server application has to listen for this message and answer it.
This way you get the server IP address and you can connect to it.
And you have to send only one message to reach all hosts in the subnet.
Example code for sending and receiving broadcast messages
Thank you everyone I ended up creating a socket connection to each IP in the network and displaying host name from the socket. it showed me all devices whether they are android devices or windows machines.
Of course since I made the socket listen at port 8000 on both device and computer, so using a socket will give result IF AND ONLY IF both ends are listening on the same port, and I only care about computers that are running my service.
I really appreciate all the suggestions and help :)
Related
I am writing a game in Java using libGDX. I want to add local area network discovery into the game, so players will only have to press a button to start a multiplayer game. To achieve this, each client broadcasts UDP packets to a certain port (255.255.255.255:40667) and listens for other incoming packets on this port to create a list of other players on the network.
This works perfectly, but the packets which were broadcasted by a machine are also received by it.
For example:
If there are 2 machines on the network with the program running
Machine 1 (192.168.1.137)
Machine 2 (192.168.1.111)
Then the 1st machine receives packets from 192.168.1.111 AND from 192.168.1.137
I am trying to find a way to determine if the packet came from my own address, but I can't figure it out.
InetAddress.getLocalHost() returns 127.0.1.1, and reading the local address from the outbound socket returns 0.0 0.0
How do I determine if the packet was sent from the same machine?
Thanks
Your machine usually has multiple IP addresses and calling to localhost often returns 127.0.1.1
There is several options how to determine local IP address, one is just to create socket connection:
// Here is the existing IP address in my local network, or you will get the exception
try (Socket socket = new Socket("192.168.0.1", 80)) {
System.out.println(socket.getLocalAddress().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You can manually assosiate your host name with address modifying:
C:\Windows\System32\drivers\etc\hosts
Add 10.10.10.1 test for example and in your app just call:
System.out.println(InetAddress.getByName("test").getHostAddress());
command hostname in cmd will return you the hostname.
Good day,
I have a java game that I want to play with a friend over network, I have implemented Sockets and tested the game on my pc using localhost as address, but was unable to connect to the external ip of my pal's pc, presumably due to us both being behind routers.
Here is the code of host/client:
CLIENT:
try {
socket = new Socket(inputHostIp(), 5555);
} catch (IOException e) {
e.printStackTrace();
}
SERVER:
try {
hostServer = new ServerSocket(5555);
} catch (IOException e1) {
e1.printStackTrace();
}
listenForUserConnection();
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
Socket socket = null;
try {
socket = hostServer.accept();
} catch (IOException e) {
e.printStackTrace();
continue;
}
joined(socket);
}
The exception I am getting now is
java.net.ConnectException: Connection timed out: connect
On trying to init I/O:
java.net.SocketException: Socket is not connected
java.net.Socket.getInputStream/java.net.Socket.getOutputStream
I have set up port forwarding with the chosen port number (5555) linked to the internal ip on both our machines.
What are my options for getting this to work?
ADDENDUM:
We have also tried using Hamachi to create a virtual LAN, but there seems to be an issue with that - we can’t ping one another even through that, it diagnoses with an issue -
Tunnel:
VPN domain's tap device is down
Local results:
Adapter configuration:
Cannot get adapter config
Traffic test: Cannot complete test
Peer results: [160-056-951]
Adapter configuration: OK
Traffic test: Inbound traffic blocked, check firewall settings
I have tried shutting down firewalls, hamachi issues changed to just ‘cannot get adapter config’, but otherwise no results.
On my pc, however, I got a version of windows that doesn’t seem to display Firewall setting properly, if you think it’s likely an issue, can you tip me on how to test my firewall?
I am writing a server which uses a DatagramChannel (non-blocking) to send/receive data. It works flawlessly on my local network, but if I try to connect to it using the client application from a different network (i.e. over the internet), I cannot reach it.
Whilst running, if I use http://ping.eu/port-chk/ to check the port, it says it's closed. I have forwarded the appropriate ports and adjusted firewalls to appropriate levels.
My code is as follows:
public void runServer(int portNo)
{
try
{
serverChannel = DatagramChannel.open();
ipAddress = InetAddress.getLocalHost();
//ipAddress = InetAddress.getByName(getPublicIP());
//serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true); //Added in to try to fix
serverChannel.socket().bind(new InetSocketAddress(portNo));
serverChannel.configureBlocking(false);
serverChannel.socket().setReceiveBufferSize(receiveBufferSize);
serverChannel.socket().setSendBufferSize(sendBufferSize);
//serverChannel.connect(new InetSocketAddress(ipAddress,portNo)); //Added in to try to fix
serverRunning = true;
}
catch(IOException e)
{
e.printStackTrace();
}
}
The parts which are commented out have had no effect. The ipAddress variable in the example will fetch the local IP, where as the commented-out version will get the public IP of the computer.
If you could help me find out why I cannot connect to this port over the internet, I would be very grateful.
You haven't forwarded the ports correctly. Nothing to do with the code.
As #EJP has suggested, there doesn't seem to be anything wrong with my code. I have since hosted this server application using Amazon EC2, and it has worked flawlessly.
There is an issue with the firmware of my router which is preventing port forwarding.
Working on a client-server android application. The clients are polling the bufferedinputstream (in) for server messages, meanwhile also repeatedly checking if server is reachable so they can terminate instantly when server goes offline.
try {
while (true) {
if (MainActivity.in.available() > 0) {
message = MainActivity.readInput();
break;
}
Thread.sleep(100);
}
} catch (IOException e) {Log.e("myoutput", e.toString()); serverOffline = true; } //server probably offline?
catch (InterruptedException e2) {}
On one of my test devices (android 2.2) this works as I thought, as soon as I close down the server the IOException is triggered. Although on my second test device (android 4.3) the IOException is not triggered (compling with API 8). But I'm starting to think this is not a device thing as I tried running both API 8 and 18 in the emulator and it didn't trigger.
Any ideas?
I'm probably not providing all essential information to get any help from here, please let me know if so and I'll provide!
I'm trying to connect to a simple Java server on my computer (in the future a true server, but I'm just learning how to program with sockets first. When I try to connect, the application on the phone throws an IOException. However, on the emulator, it does NOT.
I do have:
< uses-permission android:name="android.permission.INTERNET"/>
included in the manifest. And here's the code block that's executed when I hit open:
try {
responseField.setText("Opening socket...");
Socket socket = new Socket(getIP(),Integer.parseInt(getPort()));
responseField.setText("Socket opened. Initializing out...");
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
responseField.setText("Done. Initializing in...");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
responseField.setText("Done.");
} catch (NumberFormatException e1) {
responseField.setText("NumberFormatException");
} catch (UnknownHostException e1) {
responseField.setText("UnknownHostException");
} catch (IOException e1) {
responseField.setText("IOException");
}
Are you making sure that the server end uses a ServerSocket and uses the ServerSocker.accept() method?
So it seems that a weak Wi-Fi signal is causing error. I tried to surf the web (Google, CNN, etc.) afterward, and I could not. So I will just have to test on the emulator for now, or in a stronger signal. Thanks
If you were able to connect to the web before (I am assuming) but not after, then its not a problem with the wifi strength. Also depending on place you are surfing, the wifi router may have been configured not to allow such connections. Try to ping your server IP using a different computer within the same network and see whether you can ping. Emulator will work since the server is running on the localhost.