0
votes

Hello StackOverflow Community,

I have a specific question launching a java.net.ServerSocket on a Raspberry Pi Zero and connect to it with a java.net.Socket. The RPi is configured as a Wireless Access Point, so I can connect to it via WLAN with more than one Laptop/Tablets. The purpose is to launch a server-client game with the RPi as the server (without the need of a separate network and a server running on a device) and some devices as the clients (that can connect to the RPi).

I tried the following four situations, all more than once to prove that they always show the same result:

  1. I connected to the RPi via WLAN with a tablet. Then i launched the ServerSocket on that tablet. After that I launched a Socket on that tablet and connected it to the ServerSocket. The connection worked and data was transmitted in both directions.

  2. I connected to the RPi via WLAN with a tablet. Then i launched the ServerSocket on that tablet. After that I launched a Socket on the RPi and connected it to the ServerSocket running on my tablet. The connection worked and data was transmitted in both directions.

  3. I connected to the RPi via WLAN with a tablet. Then i launched the ServerSocket on the RPi. After that I launched a Socket on my tablet and connected it to the ServerSocket running on my RPi. The first weird thing was that the IP of the ServerSocket is 0.0.0.0, the second problem that the client failed to connect to the RPi and therefore was not able to transmit data.

  4. I connected to the RPi via WLAN with a tablet. Then i launched the ServerSocket on the RPi and bind it to a specified IP address. After that I launched a Socket on my tablet and connect it to the ServerSocket running on my RPi. The ServerSocket failed to bind to the given IP address, therefore the Socket failed to connect to the Server and therefore no data was transmitted.

Why is no IP bound (except 0.0.0.0) to the ServerSocket? Why can't I connect to the IP-Address 0.0.0.0? How can I get the ServerSocket running on the RPi with Java?

Here are the java source codes I used for all three situations:

Server:

import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.InetSocketAddress;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Server {
    private     ServerSocket    ss;

    public static void main(String[] args) {
        new Server();       // call the constructor
    }

    public Server() {
        try {
            ss = new ServerSocket(4444);    // create the ServerSocket
            new Thread(new Runnable() {     // create new Thread for listening to new clients
                public void run() {
                    startAccept();          // run the accept-clients method
                }
            }).start();     // don't forget to start the thread
            System.out.println(InetAddress.getLocalHost().getHostAddress());    // print the IP-Address
            System.out.println("4444");     // print the Port
        } catch (Exception e) {
            e.printStackTrace();        // show exceptions
        }
    }

    public void startAccept() {
        while (true) {      // listen to new clients
            try {
                Socket so = ss.accept();    // accept the clients and create reader/writer
                BufferedReader bure = new BufferedReader(new InputStreamReader(so.getInputStream()));
                BufferedWriter buwr = new BufferedWriter(new OutputStreamWriter(so.getOutputStream()));
                new Thread(new Runnable() {     // start new thread for reading from the client
                    public void run() {
                        readSocket(bure, buwr); // run the read/write method of the client
                    }
                }).start();     // don't forget to start the thread
            } catch (Exception e) {
                e.printStackTrace();        // show exceptions
            }
        }
    }

    public void readSocket(BufferedReader bure, BufferedWriter buwr) {
        while (true) {      // listen to all messages sent by the client
            try {
                String l1 = bure.readLine();            // read first line
                System.out.println("Rec1: <"+l1+">");   // show it
                String l2 = bure.readLine();            // read second line
                System.out.println("Rec2: <"+l2+">");   // show it
                buwr.write(l1+" + "+l2+" = "+(Integer.parseInt(l1)+Integer.parseInt(l2))+"\n");
                buwr.flush();       // convert both lines to integers and send the sum of them
            } catch (Exception e) {
                e.printStackTrace();        // show exceptions
            }
        }
    }
}

Client:

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Client {
    public static void main(String[] args) {        // start the program
        try {
            Socket so = new Socket();       // create an unbound socket
            so.connect(new InetSocketAddress("0.0.0.0", 4444), 10000);
                // bind socket to the IP-address printed by the Server and create reader/writer
            BufferedReader bure = new BufferedReader(new InputStreamReader(so.getInputStream()));
            BufferedWriter buwr = new BufferedWriter(new OutputStreamWriter(so.getOutputStream()));
            buwr.write("7\n4\n");   // send 7 and 4, both followed by a new line
            buwr.flush();
            System.out.println("Sent: <7\n4\n>");   // show the user what has been sent
            System.out.println("Message from Server: "+bure.readLine());    // sum sent by the server
            so.close();     // close socket
        } catch (Exception e) {
            e.printStackTrace();    // show exception
        }
    }
}

I appreciate in advance for any help on this topic.

1
I don't really understand what you mean when you say you "launched a Socket on that tablet and connected it to the ServerSocket." Can you explain in more detail? Incidentally, I suspect the problem is that "0.0.0.0" is not really an IP number. It is used when creating a listening (server) socket to mean "listen on all interfaces". When you create as a client, you will have to use a real IP number.Kevin Boone
By „launching the Socket“ i mean executing the Client source code with the IP of the Server, the connection will be created Java-internally. The „0.0.0.0“ in the Server source code is just representative. Same is for „launching the ServerSocket“ which means executing the Server source code.The_Programmer
Perhaps it would be easier to understand if you included the actual code you run, rather than just representative code? In the original question you said "Why can't I connect to the IP-Address 0.0.0.0?" This does kind of look like you're trying to, well, connection to IP address 0.0.0.0, which is not really meaningful.Kevin Boone
I tried 0.0.0.0 as well as the IP address printed by the Server, which sometimes was 0.0.0.0. It sometimes also returned 127.0.1.1, 192.168.46.123 or similar IPs, 0.0.0.0 was just the most common one.The_Programmer

1 Answers

0
votes

Finally i found a solution on my own.

The core problem was setting up the RPi as a WAP with this tutorial (without installing a brigde with bridge-utils). It is not possible to access the RPI without a defined static IP address, therefore it is not possible to bind a ServerSocket to any IP address.

Add a static IP address to the RPi WAP works that way:

Edit the file /etc/network/interfaces with

sudo nano /etc/network/interfaces

and write the following lines to the end of the file.

auto wlan0
iface wlan0 inet static
    address 192.168.5.1    #Use own IP address here
    netmask 255.255.255.0

Notes: There needs to be an empty line at the end of this file. It is not required that the static IP address is within the range defined in /etc/dnsmasq.conf, but it only works if the subnet mask fits (in my case it is 192.168.5.xxx).

The next problem was that I did not know to which IP the ServerSocket is bound to. I got weird outputs (see the comments) by calling

System.out.println(InetAddress.getLocalHost().getHostAddress());
System.out.println(ss.getInetAddress().getHostAddress());

and the query of ss.isBound() always returned true. The solution to this problem is to bind the ServerSocket to a specific IP address, which is the same as defined above in the interfaces file on the RPi. Instead of calling

ss = new ServerSocket(4444);

I used

ss = new ServerSocket();
ss.bind(new InetSocketAddress("192.168.5.1", 4444));

so the ServerSocket started bound to the static IP address I defined. Now I was able to send a message to the Server, there the message got parsed and the result was sent back to the client.