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

Android Studio(Java)客户端无法连接Android服务端问题求助

客户端无法连接TCP Socket服务端排查方案

近期刚学习TCPSocket,希望使用Android Studio开发在线答题APP,但客户端运行时无法连接到服务端,反复查阅资料、检查代码仍未解决。以下是相关代码和日志:

服务端代码

public class ServerWaitStart extends AppCompatActivity {
    private static GlobalVariable gv;

    private ServerSocket serverSocket;

    TextView currentNum;
    private int count = 0;

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

        gv = (GlobalVariable)getApplicationContext();

        TextView IPaddress = findViewById(R.id.IPaddress);
        gv.IP = getLocalIP(this);
        IPaddress.setText("群組代碼:" + gv.IP);

        currentNum = findViewById(R.id.currentNum);
        serverConnect();
    }

    private ServerThread serverThread;

    public void serverConnect(){
        try {
            serverSocket= new ServerSocket(5050);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        serverThread = new ServerThread();
        serverThread.startServer();
    }

    class ServerThread extends Thread implements Runnable{

        private boolean serverRunning;
        private int count = 1;

        public void startServer(){
            serverRunning = true;
            start();
            System.out.println("startServer execute");
        }


        @Override
        public void run() {
            try {
                while(serverRunning){
                    System.out.println("in run");
                    Socket socket = serverSocket.accept();
                    System.out.println("accept!");
                    count++;

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                                dos.writeUTF(count + "\n");
                                // 立即發送
                                dos.flush();
                                currentNum.setText("目前已加入人數" + count);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    });
                    if (gv.chooseNum == count){
                        break;
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }//ServerThread

客户端代码

public class ClientWaitStart extends AppCompatActivity {
    private GlobalVariable gv;
    private TextView currentNum;

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

        currentNum = findViewById(R.id.currentNum);
        gv = (GlobalVariable)getApplicationContext();
    }

    private Runnable Connection=new Runnable() {
        @Override
        public void run() {
            try {
                Socket socket = new Socket("10.0.2.16", 5050);
                System.out.println("client connected");

                DataInputStream dis = new DataInputStream(socket.getInputStream());
                String waitPeopleNum = dis.readUTF();

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        currentNum.setText("目前已加入人數;" + waitPeopleNum);
                    }
                });

            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    };

服务端日志

2023-06-02 13:22:19.504  5063-5063  System.out              com.appcompat.app.quiz               I  startServer execute 
2023-06-02 13:22:19.505  5063-5315  System.out              com.appcompat.app.quiz               I  in run

排查要点

  • 网络与IP一致性:
    • 服务端通过getLocalIP(this)获取IP并显示在界面,需确认该IP和客户端硬编码的10.0.2.16是否一致,可在服务端日志中打印gv.IP的值验证。
    • 若为模拟器+真机组合测试:Android模拟器访问真机服务端需用真机的局域网IP;若均为真机,确保在同一WiFi网络下,且设备防火墙未拦截5050端口。
  • 权限配置:
    • Android 9+需在AndroidManifest.xml中添加android:usesCleartextTraffic="true",允许明文Socket连接;同时必须添加网络权限:
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
      
  • 客户端线程启动:
    • 客户端仅定义了Connection Runnable,但未看到启动代码,需在合适时机(如按钮点击、onResume方法)调用new Thread(Connection).start();,且绝对不能在主线程直接执行Socket连接,否则会触发NetworkOnMainThreadException。
  • 服务端代码优化与验证:
    • ServerThread无需同时继承Thread和实现Runnable,直接继承Thread即可。
    • 服务端日志仅显示in run,说明serverSocket.accept()一直处于阻塞等待状态,证明客户端连接请求未到达服务端,优先排查网络和IP问题。
    • 避免在runOnUiThread中执行Socket IO操作,应将IO逻辑放在子线程,UI线程仅负责更新界面。
  • 端口占用检查:
    • 可尝试更换端口(如8888)测试,排除5050端口被其他应用占用的可能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 03:14:59