Setting Up Multicast Server Socket in Android - java

I found some examples for setting up a multicast socket server (receiving) in Android and I'm trying to add that to my project. My constructor code looks like this:
try
{
this.socket = new MulticastSocket (PORT);
socket.joinGroup (InetAddress.getByName (MULTICAST_ADDRESS));
}
catch (Exception ex)
{
Log.e (TAG, "Start up error: " + ex.getMessage());
ex.printStackTrace();
this.running = false;
}
However, for reasons I don't understand, every time the joinGroup() line is executed an exception is thrown. Strangely, the printStackTrace() line doesn't give me anything, but the Log.e() business gives me the following:
Multicast Server: Start up error: setsockopt failed: ENODEV (No such device)
I have added the necessary permissions to my code (CHANGE_WIFI_MULTICAST_STATE, ACCESS_WIFI_STATE, & INTERNET), and I have acquired a Multicast lock as well.
Any suggestions at what's missing here?

By a round-about-path, this question became the same as mine:
http://stackoverflow.com/questions/8180275/multicast-no-such-device
And the answer turns out to be that I needed to specify the interface, since my fancy Panasonic Android tablet has more than one:
try
{
NetworkInterface eth0 = null;
Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
while (enumeration.hasMoreElements())
{
eth0 = enumeration.nextElement();
if ("eth0".equalsIgnoreCase (eth0.getName()))
{
break;
}
}
this.socket = new MulticastSocket (PORT);
socket.setSoTimeout (60000);
socket.joinGroup (new InetSocketAddress (MULTICAST_ADDRESS, PORT), eth0);
}
catch (Exception ex)
{
...

Related

Android App can't connect with Java Server via Socket

I m trying to create a simple test application that connect via Socket to my computer (in localhost).But it thows some exception and I can't figure out how to solve it. NOTE: I m running the apk in my phone (not in an emulator)
Java Server Code
public class Main {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Thread t = new Thread(){
#Override
public void run(){
System.out.println("Server is running and listening ... ");
try{
ServerSocket ss = new ServerSocket(7000);
while(true){
Socket s = ss.accept();
System.out.println("Connesso");
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println("Received from Client: "+ dis.readUTF());
dis.close();
s.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
};
t.start();
}
}
And this is the
Andorid Client Code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button sendBTN;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendBTN=(Button)findViewById(R.id.button);
sendBTN.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Thread t = new Thread(){
#Override
public void run(){
try {
System.out.println("Starting Connection");
Socket s = new Socket("127.0.0.1", 7000);
System.out.println("Connection DONE");
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF("Let's Test The Socket");
dos.flush();
dos.close();
s.close();
System.out.println("Closing socket");
} catch (UnknownHostException e){
System.out.println("There was an Unknown Erorr:");
e.printStackTrace();
} catch (IOException e) {
System.out.println("There was an IOException:");
e.printStackTrace();
}
}
};
t.start();
Toast.makeText(this, "Messagge Sent...", Toast.LENGTH_SHORT).show();
}
}
What I get it this error:
I also tried some other ports like 1432 or 8000 or 8080 but the result is the same
Then I tried to change the IP from 127.0.0.1 to my own PC ip.. and what I get is this error..
EDIT:
I tried to run the app inside an Emulator using 10.0.2.2 as IP and everything woks fine.. I also tried to use my Private Ip in another JAVA Client program and it works fine.. So the problem is just the connection beetween my real phone and my PC (even if they are in the same network)
Make sure the IP when set to use your local machine from the emulator is 10.0.2.2
When you are using your phone and your PC:
If you are on the same network, make sure you're using the appropriate IP for your PC on your network as the server connection host. I usually set my physical machines to static IPs on my network (through my router) so I don't have to constantly look at what they are, but this is by no means a requirement.
If you are using your phone off of your home network, you will have to use the IP your ISP gives to connect, and make sure that the port is forwarded appropriately in your router if you have one set up.
In either case, you'll need to make sure the firewall is allowing incoming connections on the port you are specifying.
Ok I found the solution.
Then I deleted the exception I ve made in my firewall for port 7000 and I created a new exception which allow the connection using port 3000 and now it works fine.
If you're trying to connect the localhost listening server via Android Virtual Device, you must first check whether the "mobile data" in the AVD is in "On" state, since it doesn't work if it is in "Off" state, well I don't know the exact reason but it works like that.

Reading Data from Bluetooth Data Transfer on Android

I am looking to get/read the Data I passed after I connected a couple of Android Devices, so far I pair, connect and transmit the information between them, but not sure how to implement the reading part, here I am not sure if I should use createRfcommSocketToServiceRecord or listenUsingRfcommWithServiceRecord to create the reading socket for this purpose.
I have two screens, one where the user push a button and transmit the info and the other where the receiver press another button and read the data, I wonder if the sync is incorrect and after I push the "send" button and then the "read" button the connection is unavailable or if this implementation is just not recomendable all together.
These are my two attempts:
Attempt 1:
//Executed after the user press the read data button
private void connectToServerSocket(BluetoothDevice device, UUID uuid) {
try{
BluetoothServerSocket serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(device.getName(),uuid);
//Here is where I get the error:
//io to Server Socket JSR82 Connection is not created, failed or aborted
BluetoothSocket clientSocket = serverSocket.accept();
// Start listening for messages.
StringBuilder incoming = new StringBuilder();
listenForMessages(clientSocket, incoming);
// Add a reference to the socket used to send messages.
transferSocket = clientSocket;
} catch (IOException ioe) {
this.printToast("Excep io toServerSocket:" + ioe.getMessage());
} catch (Exception e) {
this.printToast("Excep toServerSocket:" + e.getMessage());
}
}
Attempt 2:
private void connectToServerSocket(BluetoothDevice device, UUID uuid) {
try{
BluetoothServerSocket clientSocket = device.createRfcommSocketToServiceRecord(uuid);
//clientSocket without method and invoke is not working either
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
clientSocket = (BluetoothSocket) m.invoke(device, 1);
//Here is where I get the error:
//io to Server Socket JSR82 Connection is not created, failed or aborted
clientSocket.connect();
// Start listening for messages.
StringBuilder incoming = new StringBuilder();
listenForMessages(clientSocket, incoming);
// Add a reference to the socket used to send messages.
transferSocket = clientSocket;
} catch (IOException ioe) {
this.printToast("Excep io toServerSocket:" + ioe.getMessage());
} catch (Exception e) {
this.printToast("Excep toServerSocket:" + e.getMessage());
}
}
On serverSocket.accept() or clientSocket.connect() I get the exception:
Connection is not created, failed or aborted
I would appreciate if anyone could guide me towards getting the data reading part working. Thanks.
Take a look at Android's BluetoothChat example included with the Android SDK. I think it does exactly what you want.
$ANDROID_SDK/samples/android-19/legacy/BluetoothChat/src/com/example/android/BluetoothChat
Read the managing the connection part.
Its clearly written in the documentation how to exchange (read/write) info between devices through Bluetooth. http://developer.android.com/guide/topics/connectivity/bluetooth.html

Java application getting different IP from android application - Why?

I made one android application that needs to connect one local database provided by wamp server. First using the android virtual device (AVD) my IP to connect the server first time used to be: 10.0.2.2. My AVD was connecting fine, but when I tried to connect direct on my device he wasn't finding the local server with this 10.0.2.2 IP. At this point I've changed IP to 192.168.1.5 which was my LAN cable IP, both device and AVD were running without problems... but sometimes I need to change my connection to wifi, which changes the IP..also, I realized that fix one IP in my source code will be a problem to release the android app, since other people will have other LAN IP address.
To solve this problem, I've started to look for a solution, such as acquire the LAN IP dynamically. For this purpose I built this Java application as test:
public class test {
public static void main(String[] args) throws Exception
{
String roundHost = null;
Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
for (; n.hasMoreElements();)
{
NetworkInterface e = n.nextElement();
Enumeration<InetAddress> a = e.getInetAddresses();
for (; a.hasMoreElements();)
{
InetAddress addr = a.nextElement();
if (addr.isSiteLocalAddress()){
String pureHost = addr.getByName(addr.getHostName()).toString();
roundHost = addr.getHostAddress();
pureHost = pureHost.substring(addr.getHostName().length()+1);
if(!roundHost.equals(pureHost))
break;
}
}
}
System.out.println(roundHost);
}
}
As output, this java application gives me my correct LAN wifi IP or even my LAN cable IP which is 192.168.1.3 or 192.168.1.7. From here I made one "IPParser" to use on my android app:
public class IPParser {
String pureHost, roundHost = null;
public IPParser() throws UnknownHostException{
Enumeration<NetworkInterface> n = null;
try {
n = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e1) {
e1.printStackTrace();
}
for (; n.hasMoreElements();)
{
NetworkInterface e = n.nextElement();
Enumeration<InetAddress> a = e.getInetAddresses();
for (; a.hasMoreElements();)
{
InetAddress addr = a.nextElement();
if (addr.isSiteLocalAddress()){
pureHost = addr.getByName(addr.getHostName()).toString();
roundHost = addr.getHostAddress();
pureHost = pureHost.substring(addr.getHostName().length()+1);
if(!roundHost.equals(pureHost))
break;
}
}
}
}
public String returnIp() {
return roundHost;
}
}
As you can see it's pretty similar; the difference is just some structural changes to adapt the needed syntax. And now comes the real problem: When I try to run this parser inside my AVD, my ip is 10.0.2.15 and running directly in my device the ip return is 192.168.1.6 - Obviously the android app is crashing because it can't find the local server to connect.
My IP config information:
I'm not an expert in network, so I ask, take it easy and if I said something technically wrong or adjacents please edit and correct me..finally I ask:
Why this is happening and what's possible to do to solve this problem?
The IPs you mention (10.0.2.2 and 192.168.1.5) are from two different networks, which makes sense since the documentation states that:
Each instance of the emulator runs behind a virtual router/firewall
service that isolates it from your development machine's network
interfaces and settings and from the internet. An emulated device can
not see your development machine or other emulator instances on the
network. Instead, it sees only that it is connected through Ethernet
to a router/firewall.
The virtual router for each instance manages the 10.0.2/24 network
address space — all addresses managed by the router are in the form of
10.0.2., where is a number. Addresses within this space are pre-allocated by the emulator/router as follows:
What this means is that when using the AVD there is a virtual network that is created which the device and the computer are part of. In your case your local machine takes the address 10.0.2.2 in this virtual network and the AVD 10.0.2.15. But when you connect directly through your device, the computer's IP (as well as the device's) is in the LAN's address space (i.e. 192.168.1.5 and 192.168.1.6).
The code you posted resolves the IP address of the host, but if you want the device to resolve automatically the server's IP address and you can guarantee they will always be both connected to the same LAN, then you can use multicast UDP messages (I didn't find a really good source but you can start here, here and here). This type of communication sends a UDP datagram to the network to a specific multicast IP address and port, to which other devices in the network are listening. I've used this scheme in an Android application that needed to find a computer in the network so I know for a fact that it works. I can share some code if you need to.
EDIT
The following snippets of code are the ones that implement the search of computers in the network. The Android application this was used in could control the mouse and keyboard of any computer in the network that had the server application running.
Android Client
public void findComputers(View v) {
try {
int port = 4444;
String multicastAddr = "224.168.1.0";
DatagramSocket socket = new DatagramSocket(port);
socket.setSoTimeout(300);
InetAddress group = InetAddress
.getByName(multicastAddr);
DatagramPacket packet = new DatagramPacket(new byte[] { 1 }, 1,
group, port);
socket.send(packet);
// Give time to the servers to respond
Thread.sleep(100);
while (true) {
try {
// Listen for the servers responses
byte[] buffer = new byte[256];
packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String data = new String(packet.getData());
// Information sent from servers include the host's name
// and IP addres separated by a semicolon.
String[] parts = data.split(";");
// Add a server to the result list.
Computer computer = new Computer(parts[1].trim(),
parts[0].trim());
this.computers.put(computer.getName(), computer);
} catch (InterruptedIOException ex) {
break;
}
}
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
String output = "No computers found.";
if (this.computers.size() > 0) {
output = this.computers.size() + " computer(s) found.";
this.fillComputers();
}
Toast.makeText(this, output, Toast.LENGTH_SHORT).show();
}
Server
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* Receives UDP broadcast packets in the default port requesting for server name
* and IP, broadcasting the information in return.
*
* #author jfacorro
*
*/
public class NameResolverService extends Thread {
private InetAddress localAddress = null;
private byte[] localAddressData = null;
private MulticastSocket socket = null;
private boolean exit = false;
public NameResolverService() {
}
public void exit() {
this.exit = true;
this.socket.close();
}
#Override
public void run() {
try {
int port = 4444;
String multicastAddr = "224.168.1.0";
// Get current address
this.localAddress = InetAddress.getLocalHost();
this.socket = new MulticastSocket(port);
InetAddress group = InetAddress.getByName(multicastAddr);
this.socket.joinGroup(group);
this.localAddressData = (this.localAddress.getHostAddress() + ";" + this.localAddress
.getHostName()).getBytes();
} catch (IOException ex) {
this.notified.notified(ex.getMessage());
ex.printStackTrace();
}
while (!this.exit) {
try {
byte[] buffer = new byte[1];
DatagramPacket packet = new DatagramPacket(buffer,
buffer.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(this.localAddressData,
this.localAddressData.length, address, port);
socket.send(packet);
} catch (IOException e) {
if(!this.exit)
e.printStackTrace();
}
}
this.socket.close();
}
}

Client-Server Program, can connect from Java client but not from Android

I have a working Java client/server program which is very straightforward and basic. This works fine. However, I am now trying to write an Android client, and I have been unable to connect to the server from my android client. I am using almost identical code for the android networking code as I use for the normal client. My android code is simple, all it does is starts this thread from onCreate:
private int serverPort = 8889;
private String serverIP = "192.168.5.230";
private Socket socket = null;
private Thread clientThread = new Thread("ClientThread") {
#Override
public void run() {
try {
socket = new Socket();
socket.connect(new InetSocketAddress(serverIP, serverPort), 1000);
DataInputStream din = new DataInputStream( socket.getInputStream());
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
while (true) {
String message = din.readUTF();
setPicture("picture1");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
The port is the correct port my server is running on, as is the ip address (which I got from ifconfig since I know you cannot use localhost). When I run my normal pc client with the same port and IP address, the connection goes through. But when I run this code on my android device, the socket timesout when I try to connect.
Does anyone have any suggestions for where I am going wrong?
Double check that you added the permission requirement in the manifest file:
<uses-permission android:name="android.permission.INTERNET" />
But, possibly more importantly, 192.168.x.x is a local or non-routable network so you need to be on the same network, or one that knows how to reach the 192.168.5.230 address. You say that it doesn't work when you try it on your device -- are you running on local wifi when you run or are you on your mobile network? If you're on mobile, try it from wifi.

Java Networking "Connection Refused: Connect"

I have been trying to get a simple networking test program to run with no results.
Server:
import java.io.*;
import java.net.*;
public class ServerTest {
public static void main(String[] args) {
final int PORT_NUMBER = 44827;
while(true) {
try {
//Listen on port
ServerSocket serverSock = new ServerSocket(PORT_NUMBER);
System.out.println("Listening...");
//Get connection
Socket clientSock = serverSock.accept();
System.out.println("Connected client");
//Get input
BufferedReader br = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
System.out.println(br.readLine());
br.close();
serverSock.close();
clientSock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Client:
import java.io.*;
import java.net.*;
public class ClientTest {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44827;
final String HOSTNAME = "xx.xx.xx.xx";
//Attempt to connect
try {
Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
//Output
out.println("Test");
out.flush();
out.close();
sock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
The program works just fine when I use 127.0.0.1 or my internal IP for the hostname. But whenever I switch to my external IP address, it throws a java.net.ConnectException: Connection refused: connect error.
I purposely picked such an uncommon port to see if that was the problem, with no luck.
I can connect with no problems using telnet, but when I try to access the port with canyouseeme.org, it tells me the connection timed out.
I even tried to disable all firewalls and antivirus including the Windows default ones and the router firewall, with all ports forwarded and DMZ enabled, and it still says that the connection timed out. I use Comcast as my ISP, and I doubt that they block such a random port.
When I use a packet tracer, it shows TCP traffic with my computer sending SYN and receiving RST/ACK, so it looks like a standard blocked port, and no other suspicious packet traffic was going on.
I have no idea what is going on at this point; I have pretty much tried every trick I know. If anyone know why the port might be blocked, or at least some way to make the program work, it would be very helpful.
These problem comes under the following situations:
Client and Server, either or both of them are not in network.
Server is not running.
Server is running but not listening on port, client is trying to connect.
Firewall is not permitted for host-port combination.
Host Port combination is incorrect.
Incorrect protocol in Connecting String.
How to solve the problem:
First you ping destination server. If that is pinging properly,
then the client and server are both in network.
Try connected to server host and port using telnet. If you are
able to connect with it, then you're making some mistakes in the client code.
For what it's worth, your code works fine on my system.
I hate to say it, but it sounds like a firewall issue (which I know you've already triple-checked) or a Comcast issue, which is more possible than you might think. I'd test your ISP.
Likely the server socket is only being bound to the localhost address. You can bind it to a specific IP address using the 3-argument form of the constructor.
I assume you are using a Router to connect to Internet. You should do Port Forwarding to let public access your internal network. Have a look at How do you get Java sockets working with public IPs?
I have also written a blog post about Port forwarding, you might wanna have a look :) http://happycoders.wordpress.com/2010/10/03/how-to-setup-a-web-server-by-yourself/
But I still couldn't get this accessed over public IP, working on it now...
I had the same problem because sometimes the client started before server and, when he tried to set up the connection, it couldn't find a running server.
My first (not so elegant) solution was to stop the client for a while using the sleep method:
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
I use this code just before the client connection, in your example, just before Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
My second solution was based on this answer. Basically I created a method in the client class, this method tries to connect to the server and, if the connection fails, it waits two seconds before retry.
This is my method:
private Socket createClientSocket(String clientName, int port){
boolean scanning = true;
Socket socket = null;
int numberOfTry = 0;
while (scanning && numberOfTry < 10){
numberOfTry++;
try {
socket = new Socket(clientName, port);
scanning = false;
} catch (IOException e) {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return socket;
}
As you can see this method tries to create a socket for ten times, then returns a null value for socket, so be carefull and check the result.
Your code should become:
Socket sock = createClientSocket(HOSTNAME, PORT_NUMBER);
if(null == sock){ //log error... }
This solution helped me, I hope it helps you as well. ;-)

Categories

Resources