You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android客户端与Java服务器消息收发及广播实现方案问询

Alright, let's get your Android client and Java server set up for one-to-many messaging. I'll walk you through finishing the server logic first, then build out the Android client to send and receive broadcasted messages.

1. Complete the Java Server (Message Receive + Broadcast)

Your existing code snippet cuts off, so let's build out the full server logic. The key here is maintaining a thread-safe list of connected clients and broadcasting incoming messages to everyone.

Here's the full, functional server code:

package server1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

public class ChatServer {
    // Thread-safe list to hold output streams of all connected clients
    private static final CopyOnWriteArrayList<PrintWriter> clientWriters = new CopyOnWriteArrayList<>();

    public static void main(String[] args) {
        System.out.println("Server starting on port 8888...");
        try (ServerSocket serverSocket = new ServerSocket(8888)) {
            // Keep accepting new client connections indefinitely
            while (true) {
                new ClientHandler(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            System.err.println("Server error: " + e.getMessage());
        }
    }

    // Inner thread class to handle communication with a single client
    private static class ClientHandler extends Thread {
        private final Socket clientSocket;
        private PrintWriter out;
        private BufferedReader in;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        @Override
        public void run() {
            try {
                // Initialize input/output streams for the client
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new PrintWriter(clientSocket.getOutputStream(), true);

                // Add this client's output stream to the broadcast list
                clientWriters.add(out);
                System.out.println("New client connected. Total clients: " + clientWriters.size());

                String incomingMessage;
                // Listen for messages from the client until they disconnect
                while ((incomingMessage = in.readLine()) != null) {
                    System.out.println("Received: " + incomingMessage);
                    broadcastMessage(incomingMessage);
                }
            } catch (IOException e) {
                System.out.println("Client connection error: " + e.getMessage());
            } finally {
                // Clean up resources when the client disconnects
                try {
                    if (in != null) in.close();
                    if (out != null) {
                        clientWriters.remove(out);
                        out.close();
                    }
                    clientSocket.close();
                    System.out.println("Client disconnected. Total clients: " + clientWriters.size());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // Send the received message to all connected clients
        private void broadcastMessage(String message) {
            for (PrintWriter writer : clientWriters) {
                writer.println(message);
            }
        }
    }
}

Key Server Details:

  • We use CopyOnWriteArrayList for client streams because it's thread-safe, which is critical when multiple client threads are modifying the list simultaneously.
  • Each client connection gets its own ClientHandler thread, so the main server thread doesn't get blocked waiting for individual clients.
  • When a client sends a message, we immediately broadcast it to every other connected client via their PrintWriter.
2. Android Client Implementation (Send + Receive Messages)

Android won't let you run network operations on the main thread, so we'll use AsyncTask (for Java) to handle background network work. First, add the required permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Client Activity Code

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ChatClientActivity extends AppCompatActivity {
    private EditText messageInput;
    private TextView chatLog;
    private Button sendBtn;

    private Socket serverSocket;
    private PrintWriter out;
    private BufferedReader in;
    private ReceiveMessagesTask receiveTask;

    // Replace with your server's local IP (find via ipconfig/ifconfig on server machine)
    private static final String SERVER_IP = "192.168.1.105";
    private static final int SERVER_PORT = 8888;

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

        messageInput = findViewById(R.id.et_message);
        chatLog = findViewById(R.id.tv_chat_log);
        sendBtn = findViewById(R.id.btn_send);

        // Connect to server when the activity starts
        new ConnectToServerTask().execute();

        sendBtn.setOnClickListener(v -> {
            String message = messageInput.getText().toString().trim();
            if (!message.isEmpty() && out != null) {
                out.println(message);
                messageInput.setText("");
                // Show your own message locally
                runOnUiThread(() -> chatLog.append("You: " + message + "\n"));
            }
        });
    }

    // AsyncTask to handle initial server connection
    private class ConnectToServerTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                serverSocket = new Socket(SERVER_IP, SERVER_PORT);
                out = new PrintWriter(serverSocket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (success) {
                chatLog.append("Connected to server!\n");
                // Start listening for incoming messages
                receiveTask = new ReceiveMessagesTask();
                receiveTask.execute();
            } else {
                chatLog.append("Failed to connect. Check server IP and port.\n");
            }
        }
    }

    // AsyncTask to listen for broadcasted messages from the server
    private class ReceiveMessagesTask extends AsyncTask<Void, String, Void> {
        @Override
        protected Void doInBackground(Void... voids) {
            String incomingMessage;
            try {
                while ((incomingMessage = in.readLine()) != null) {
                    publishProgress(incomingMessage);
                }
            } catch (IOException e) {
                publishProgress("Disconnected from server.");
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            // Update UI with received message (runs on main thread)
            chatLog.append("Other Client: " + values[0] + "\n");
        }
    }

    // Clean up resources when the activity is destroyed
    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (in != null) in.close();
            if (out != null) out.close();
            if (serverSocket != null) serverSocket.close();
            if (receiveTask != null) receiveTask.cancel(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client Layout (activity_chat_client.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_chat_log"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#f5f5f5"
        android:padding="8dp"
        android:textSize="16sp"/>

    <EditText
        android:id="@+id/et_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type your message..."
        android:layout_marginTop="8dp"/>

    <Button
        android:id="@+id/btn_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send"
        android:layout_gravity="end"
        android:layout_marginTop="8dp"/>

</LinearLayout>

Key Client Details:

  • We use two AsyncTasks: one to connect to the server, another to listen for incoming broadcast messages.
  • All UI updates happen on the main thread via runOnUiThread or onProgressUpdate (since background threads can't touch UI elements).
  • We clean up all socket and stream resources in onDestroy to avoid memory leaks.
3. Test the Flow
  1. Start your Java server first (make sure your server's firewall allows incoming connections on port 8888).
  2. Ensure your Android device/emulator is on the same local network as the server.
  3. Replace SERVER_IP in the client code with your server's local IP address (find it via ipconfig on Windows or ifconfig on Linux/Mac).
  4. Launch multiple client instances (use multiple emulators or real devices).
  5. Send a message from one client—all other clients should receive the broadcasted message instantly!

内容的提问来源于stack exchange,提问作者Mirko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:51:15