基于 P2P 技术的 Android 局域网内设备通信实践

Android 局域网内的多设备通信方式有多种,其中常见的方式有:

  1. 基于 TCP/UDP 的 Socket 通信
  2. 基于 Bluetooth 的近场通信
  3. 基于 Wifi 的 Wi-Fi Direct 连接
  4. 基于第三方框架的通信,如 MQTT、Websocket 等

每种方式都有其适用范围,下面分别介绍一下它们的示例代码、优劣势。

1. 基于 TCP/UDP 的 Socket 通信

Socket 是 TCP/UDP 套接字的抽象,通常用于实现网络上的应用程序通信。基于 Socket 的通信方式可以实现高效的传输,支持实时数据处理,其主要缺点是需要进行网络编程和网络拓扑发现。

下面是一个基于 TCP 的 Socket 通信示例,它通过创建一个服务器 Socket 和客户端 Socket 实现简单的数据传输:

// 服务器端代码
public class Server {
    public static void main(String[] args) throws Exception {
        // 创建一个服务器 Socket,绑定到指定的端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器已启动,等待客户端连接...");

        // 等待客户端连接
        Socket socket = serverSocket.accept();
        System.out.println("客户端已连接[" + socket.getInetAddress().getHostAddress() + "]");

        // 获取输入输出流
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        // 循环读取客户端发送的数据
        while (true) {
            String data = reader.readLine();
            System.out.println("客户端发送了消息:" + data);

            // 发送响应消息给客户端
            writer.write("服务端收到了消息[" + data + "]");
            writer.newLine();
            writer.flush();
        }
    }
}
// 客户端代码
public class Client {
    public static void main(String[] args) throws Exception {
        // 创建一个 Socket 连接服务器
        Socket socket = new Socket("localhost", 8888);

        // 获取输入输出流
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        // 循环向服务器发送数据
        while (true) {
            // 发送消息给服务器
            writer.write("Hello, World!");
            writer.newLine();
            writer.flush();

            // 接收服务器响应消息
            String data = reader.readLine();
            System.out.println("服务器返回了响应消息:" + data);

            Thread.sleep(1000);
        }
    }
}

在上面的代码中,我们使用 Java 中的 ServerSocket 和 Socket 类来实现基于 TCP 的 Socket 通信。服务器端通过创建一个服务器 Socket 并等待客户端连接,收到连接请求后可以使用输入输出流来实现数据传输。客户端通过创建一个 Socket 向服务器发起连接,并使用输入输出流发送和接收数据。

2. 基于 Bluetooth 的近场通信

Bluetooth 是一种典型的无线短距离通信技术,它可以在近距离范围内实现设备之间的通信。Android 提供了 BluetoothAdapter 和 BluetoothSocket 等 API 来支持基于 Bluetooth 的通信,它们可以实现设备之间的数据传输、文件传输等功能。其主要缺点是受制于蓝牙信号的干扰和距离限制。

以下是一个基于 Bluetooth 的数据传输示例,它通过使用 BluetoothSocket 类实现数据传输:

// 服务端代码
public class ServerActivity extends AppCompatActivity {
    private static final int REQUEST_ENABLE_BT = 123;
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothServerSocket serverSocket;
    private Thread acceptThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server);

        // 初始化 BluetoothAdapter
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }

        // 开启蓝牙
        if (!bluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_ENABLE_BT);
        }

        // 服务端开启监听线程
        acceptThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 创建 BluetoothServerSocket
                    serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("BluetoothServer", UUID.randomUUID());

                    while (true) {
                        // 等待客户端连接
                        BluetoothSocket clientSocket = serverSocket.accept();
                        Log.d("Server", "客户端已连接:" + clientSocket.getRemoteDevice().getName());

                        // 获取输入输出流
                        InputStream inputStream = clientSocket.getInputStream();
                        OutputStream outputStream = clientSocket.getOutputStream();

                        // 读取客户端发送的数据
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        String data = reader.readLine();
                        Log.d("Server", "客户端发送的数据是:" + data);

                        // 发送响应给客户端
                        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
                        writer.write("服务端收到了数据[" + data + "]");
                        writer.newLine();
                        writer.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        acceptThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 关闭服务端 Socket
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 停止监听线程
        if (acceptThread != null) {
            acceptThread.interrupt();
        }
    }
}
// 客户端代码
public class ClientActivity extends AppCompatActivity {
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothDevice serverDevice;
    private BluetoothSocket socket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);

        // 查找蓝牙设备
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
        for (BluetoothDevice device : devices) {
            if ("BluetoothServer".equals(device.getName())) {
                serverDevice = device;
                break;
            }
        }

        if (serverDevice == null) {
            Toast.makeText(this, "未找到配对设备", Toast.LENGTH_SHORT).show();
            return;
        }

        // 连接蓝牙服务端
        try {
            socket = serverDevice.createRfcommSocketToServiceRecord(UUID.randomUUID());
            socket.connect();
            Log.d("Client", "连接服务器成功:" + socket.getRemoteDevice().getName());

            // 获取输入输出流
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();

            // 向服务端发送数据
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
            writer.write("Hello, World!");
            writer.newLine();
            writer.flush();

            // 读取服务端响应数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String data = reader.readLine();
            Log.d("Client", "服务端返回的响应:" + data);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 关闭客户端 Socket
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在上面的代码中,我们使用了 BluetoothAdapter 和 BluetoothSocket 类来实现基于 Bluetooth 的近场通信。服务端通过创建蓝牙服务器 Socket 并等待客户端连接,客户端通过创建一个蓝牙 Socket 连接服务器。在每次通信时,我们都通过输入输出流来发送和接收数据。

3. 基于 Wifi 的 Wi-Fi Direct 连接

Wi-Fi Direct 是一种 P2P 网络连接方式,它使用 Wi-Fi 技术来实现设备之间的直接通信。如果设备支持 Wi-Fi Direct,我们可以使用 Android 提供的 WifiP2pManager 类并结合 WifiP2pManager.Channel 类来实现基于 Wi-Fi Direct 的通信。其主要优势是无需路由器就可以建立点对点连接,传输速度较快。缺点是目前有一定的兼容性限制,且Wi-Fi 信号干扰和距离限制较大。

以下是一个基于 Wi-Fi Direct 的数据传输示例,它使用 WifiP2pManager 和 WifiP2pManager.Channel 类来实现数据传输:

// 服务端代码
public class ServerActivity extends AppCompatActivity {
    private WifiP2pManager wifiP2pManager;
    private WifiP2pManager.Channel channel;
    private BroadcastReceiver receiver;
    private ServerSocket serverSocket;
    private Thread acceptThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server);

        // 初始化 WifiP2pManager
        wifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
        if (wifiP2pManager == null) {
            Toast.makeText(this, "该设备不支持 Wi-Fi Direct", Toast.LENGTH_SHORT).show();
            return;
        }

        // 初始化 Channel
        channel = wifiP2pManager.initialize(this, getMainLooper(), null);

        // 注册广播接收器
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                    // Wi-Fi Direct 状态发生变化
                    int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
                    if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                        Log.d("Server", "Wi-Fi Direct 已启用");
                    } else {
                        Log.d("Server", "Wi-Fi Direct 已停用");
                    }

                } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
                    // 设备列表发生变化
                    wifiP2pManager.requestPeers(channel, new WifiP2pManager.PeerListListener() {
                        @Override
                        public void onPeersAvailable(WifiP2pDeviceList peers) {
                            for (WifiP2pDevice device : peers.getDeviceList()) {
                                Log.d("Server", "发现设备:" + device.deviceName + ", " + device.deviceAddress);

                                // 开始连接设备
                                if (device.deviceName.equals("client")) {
                                    WifiP2pConfig config = new WifiP2pConfig();
                                    config.deviceAddress = device.deviceAddress;
                                    wifiP2pManager.connect(channel, config, new WifiP2pManager.ActionListener() {
                                        @Override
                                        public void onSuccess() {
                                            Log.d("Server", "连接设备成功");
                                        }

                                        @Override
                                        public void onFailure(int reason) {
                                            Log.d("Server", "连接设备失败:" + reason);
                                        }
                                    });
                                }
                            }
                        }
                    });

                } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
                    // 连接状态发生变化
                    NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
                    if (networkInfo.isConnected()) {
                        // 建立连接
                        Log.d("Server", "连接已建立");

                        // 创建服务器 Socket
                        try {
                            serverSocket = new ServerSocket(8888);
                            Log.d("Server", "服务器 Socket 已创建");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        // 开启接收线程监听客户端连接
                        acceptThread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                while (true) {
                                    try {
                                        // 等待客户端连接
                                        final Socket socket = serverSocket.accept();
                                        Log.d("Server", "客户端已连接:" + socket.getInetAddress());

                                        // 读取客户端发送的数据
                                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                        String data = reader.readLine();

                                        // 发送响应给客户端
                                        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                        writer.write("服务端收到了数据[" + data + "]");
                                        writer.newLine();
                                        writer.flush();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        });
                        acceptThread.start();

                    } else {
                        // 断开连接
                        Log.d("Server", "连接已断开");
                        if (serverSocket != null) {
                            try {
                                serverSocket.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        if (acceptThread != null) {
                            acceptThread.interrupt();
                        }
                    }

                } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                    // 本设备信息发生变化
                    WifiP2pDevice device = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
                    Log.d("Server", "本设备信息发生变化:" + device.deviceName + ", " + device.deviceAddress);
                }
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
        registerReceiver(receiver, filter);

        // 发现并连接设备
        wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                Log.d("Server", "开始查找设备");
            }

            @Override
            public void onFailure(int reason) {
                Log.d("Server", "查找设备失败:" + reason);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 关闭服务端 Socket
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 停止监听线程
        if (acceptThread != null) {
            acceptThread.interrupt();
        }

        // 注销广播接收器
        unregisterReceiver(receiver);
    }
}
// 客户端代码
public class ClientActivity extends AppCompatActivity {
    private WifiP2pManager wifiP2pManager;
    private WifiP2pManager.Channel channel;
    private BroadcastReceiver receiver;
    private WifiP2pDevice serverDevice;
    private Socket socket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);

        // 初始化 WifiP2pManager
        wifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
        if (wifiP2pManager == null) {
            Toast.makeText(this, "该设备不支持 Wi-Fi Direct", Toast.LENGTH_SHORT).show();
            return;
        }

        // 初始化 Channel
        channel = wifiP2pManager.initialize(this, getMainLooper(), null);

        // 注册广播接收器
        receiver = new BroadcastReceiver() {
            @Override
            public            void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                    // Wi-Fi Direct 状态发生变化
                    int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
                    if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                        Log.d("Client", "Wi-Fi Direct 已启用");
                    } else {
                        Log.d("Client", "Wi-Fi Direct 已停用");
                    }

                } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
                    // 设备列表发生变化
                    wifiP2pManager.requestPeers(channel, new WifiP2pManager.PeerListListener() {
                        @Override
                        public void onPeersAvailable(WifiP2pDeviceList peers) {
                            for (WifiP2pDevice device : peers.getDeviceList()) {
                                Log.d("Client", "发现设备:" + device.deviceName + ", " + device.deviceAddress);

                                // 记录服务端设备
                                if (device.deviceName.equals("server")) {
                                    serverDevice = device;
                                }
                            }
                        }
                    });

                } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
                    // 连接状态发生变化
                    NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
                    if (networkInfo.isConnected()) {
                        // 建立连接
                        Log.d("Client", "连接已建立");

                        // 请求连接信息
                        wifiP2pManager.requestConnectionInfo(channel, new WifiP2pManager.ConnectionInfoListener() {
                            @Override
                            public void onConnectionInfoAvailable(WifiP2pInfo info) {
                                if (info.groupFormed && info.isGroupOwner) {
                                    // 服务端不需要做额外处理
                                    Log.d("Client", "该设备为服务端");

                                } else if (info.groupFormed) {
                                    // 客户端发起连接
                                    Log.d("Client", "该设备为客户端");

                                    try {
                                        socket = new Socket();
                                        socket.connect(new InetSocketAddress(serverDevice.deviceAddress, 8888), 5000);
                                        Log.d("Client", "连接服务器成功:" + socket.getInetAddress());

                                        // 向服务端发送数据
                                        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                        writer.write("Hello, World!");
                                        writer.newLine();
                                        writer.flush();

                                        // 读取服务端响应数据
                                        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                        String data = reader.readLine();
                                        Log.d("Client", "服务端返回的响应:" + data);

                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        });

                    } else {
                        // 断开连接
                        Log.d("Client", "连接已断开");
                        if (socket != null) {
                            try {
                                socket.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                    // 本设备信息发生变化
                    WifiP2pDevice device = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
                    Log.d("Client", "本设备信息发生变化:" + device.deviceName + ", " + device.deviceAddress);
                }
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
        filter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
        registerReceiver(receiver, filter);

        // 扫描设备
        wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                Log.d("Client", "开始查找设备");
            }

            @Override
            public void onFailure(int reason) {
                Log.d("Client", "查找设备失败:" + reason);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 关闭客户端 Socket
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 注销广播接收器
        unregisterReceiver(receiver);
    }
}

在上面的代码中,我们使用了 WifiP2pManager 和 WifiP2pManager.Channel 类来实现基于 Wi-Fi Direct 的通信。服务端通过创建服务器 Socket 并等待客户端连接,客户端通过创建一个 Socket 连接服务器。在每次通信时,我们都通过输入输出流来发送和接收数据。

至此,我们介绍了 Android 中常见的几种局域网通信方式,并给出了示例代码。不同的通信方式有不同的适用场景和特点,开发者可以根据实际需求选择合适的通信方式进行开发。除了局域网通信,如果需要进行远程通信,可以使用云服务提供商的 API,比如阿里云、腾讯云、AWS 等。这些云服务提供商提供了丰富的服务和 API,可以满足不同的需求,比如对象存储、云数据库、虚拟机、消息队列等等。

以阿里云为例,可以使用阿里云的移动推送服务,实现消息的推送和设备间的通信。例如,我们可以使用阿里云移动推送 SDK 将消息推送给指定的设备或者设备群组,也可以使用自定义消息进行设备间的通信。推送服务的使用需要先在阿里云控制台创建应用,并配置相关参数,然后在客户端集成移动推送 SDK,根据文档进行 API 调用即可。

此外,阿里云还提供了多种云计算服务,可以用于搭建云服务器、存储数据、处理数据等等。比如,我们可以使用阿里云的云服务器 ECS 来搭建一个 Web 服务器,将自己的应用部署到云服务器上,并使用域名解析服务进行域名解析,实现较为稳定和可靠的远程通信。

当然,不同的云服务提供商提供的服务和 API 也有所不同,开发者可以根据需求进行选择。但无论是局域网通信还是云服务通信,都需要进行网络编程和安全认证,具有一定的复杂性。因此,建议在开发前仔细阅读文档,并根据需求进行合理的设计和实现。

你可能感兴趣的:(Android,Socket,p2p,android,网络)