Java + Raspberry Pi + ServerSocket

Java + Raspberry Pi + ServerSocket

你好 Whosebug 社区,

我有一个启动 java.net.ServerSocket on a Raspberry Pi Zero and connect to it with a java.net.Socket 的具体问题。 RPi 配置为无线接入点,因此我可以通过 WLAN 与多个 Laptop/Tablets 连接。目的是启动一个服务器-客户端游戏,以 RPi 作为服务器(不需要单独的网络和设备上的服务器 运行)和一些设备作为客户端(可以连接到 RPi) .

我尝试了以下四种情况,都不止一次地证明它们总是显示相同的结果:

  1. 我用平板电脑通过 WLAN 连接到树莓派。然后我在那台平板电脑上启动了 ServerSocket。之后,我在该平板电脑上启动了一个套接字并将其连接到 ServerSocket。连接正常,数据双向传输。

  2. 我用平板电脑通过 WLAN 连接到树莓派。然后我在那台平板电脑上启动了 ServerSocket。之后,我在 RPi 上启动了一个 Socket ,并将它连接到我平板电脑上的 ServerSocket 运行。连接正常,数据双向传输。

  3. 我用平板电脑通过 WLAN 连接到树莓派。然后我在 RPi 上启动了 ServerSocket 。之后,我在我的平板电脑上启动了一个 Socket,并将它连接到我的 RPi 上的 ServerSocket 运行。第一个奇怪的是ServerSocket的IP是0.0.0.0,第二个是客户端连接树莓派失败导致无法传输数据

  4. 我用平板电脑通过 WLAN 连接到树莓派。然后我在 RPi 上启动了 ServerSocket 并将其绑定到指定的 IP 地址。之后,我在我的平板电脑上启动了一个 Socket,并将它连接到我的 RPi 上的 ServerSocket 运行。 ServerSocket 无法绑定到给定的 IP 地址,因此 Socket 无法连接到服务器,因此没有数据传输。

为什么没有IP绑定到ServerSocket(0.0.0.0除外)?为什么我无法连接到 IP 地址 0.0.0.0?如何使用 Java 在 RPi 上获取 ServerSocket 运行?

以下是我在所有三种情况下使用的 java 源代码:

服务器:

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
            }
        }
    }
}

客户:

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
        }
    }
}

非常感谢您对此主题的任何帮助。

最后我自己找到了解决办法。

核心问题是将 RPi 设置为具有 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 任何 IP 地址的 WAP。

将静态 IP 地址添加到 RPi WAP 的工作方式如下:

编辑文件/etc/network/interfaces
sudo nano /etc/network/interfaces

并将以下行写入文件末尾。

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

注意:该文件末尾需要有一个空行。不需要静态 IP 地址在 /etc/dnsmasq.conf 中定义的范围内,但只有在子网掩码适合时才有效(在我的例子中是 192.168.5.xxx)。

下一个问题是我不知道ServerSocket绑定到哪个IP。我通过调用

得到了奇怪的输出(见评论)
System.out.println(InetAddress.getLocalHost().getHostAddress());
System.out.println(ss.getInetAddress().getHostAddress());

ss.isBound() 的查询总是返回 true。这个问题的解决方案是将ServerSocket绑定到一个特定的IP地址,这个IP地址与上面在RPi上的interfaces文件中定义的相同。而不是调用

ss = new ServerSocket(4444);

我用过

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

所以 ServerSocket 开始绑定到我定义的静态 IP 地址。 现在我可以向服务器发送消息,消息在那里被解析,结果被发送回客户端。