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

Python服务器向Android客户端发数据并在TextView显示的问题求助

问题分析与解决方案

我帮你梳理出了几个导致功能失效的核心问题,咱们一步步来修正:

1. 最关键的问题:通信协议不匹配

你的Python服务器用的是TCP协议(socket(AF_INET, SOCK_STREAM)),但Android客户端却用了UDP协议(DatagramSocket)。这两种协议完全不兼容,必须统一成同一种才能正常通信。

2. Python服务器的发送对象错误

服务器里你用了监听套接字tcpSerSock.send()来发数据,但实际上应该用和客户端建立连接的通信套接字tcpCliSock——tcpSerSock只负责监听新连接,不负责和具体客户端交互。

3. Python语法与判断逻辑错误

  • 你的代码是Python2环境,print语句需要加括号;
  • Python2里字符串本身就是字节流,不需要str.encode(),直接发送字符串即可;
  • 你当前判断触发发送的条件是data == ctrCmd[5](对应Connect),但Android发送的是Balls,对应ctrCmd[6],这个判断永远不会触发。

4. Android客户端的协议适配

如果改成TCP协议,客户端需要用Socket而非DatagramSocket来实现面向连接的通信。


修正后的Python服务器代码(TCP)

import apptopi
from socket import *
from nanpy import (ArduinoApi, SerialManager)
apptopi.setup()
connection = SerialManager()
a = ArduinoApi(connection = connection)
ctrCmd = ['Up','Down','Left','Right','Stop','Connect','Balls']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)  # 设置合理的连接队列长度
print('Waiting for connection')

try:
    while True:
        tcpCliSock,addr = tcpSerSock.accept()
        print('...connected from :', addr)
        try:
            while True:
                data = tcpCliSock.recv(BUFSIZE).strip()  # 去除首尾空白,避免数据带换行/空格
                if not data:
                    break
                print('Received data from client: ' + data)
                if data == ctrCmd[0]:
                    apptopi.forw()
                    print('forward')
                elif data == ctrCmd[1]:
                    apptopi.back()
                    print('backward')
                elif data == ctrCmd[2]:
                    apptopi.left()
                    print('leftturn')
                elif data == ctrCmd[3]:
                    apptopi.right()
                    print('rightturn')
                elif data == ctrCmd[4]:
                    apptopi.stp()
                    print('stop')
                elif data == ctrCmd[6]:  # 匹配Android发送的Balls命令
                    add = 1  # 如需累加可将变量移至外层循环
                    tcpCliSock.send(str(add))  # Python2直接发送字符串
                    print('Sent data to client: ' + str(add))
        except Exception as e:
            print('Client connection error:', e)
            tcpCliSock.close()
except KeyboardInterrupt:
    apptopi.close()
    # GPIO.cleanup()  # 若未导入GPIO模块请注释此行
    tcpSerSock.close()
    print('Server closed')

修正后的Android客户端代码(TCP)

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mEditTextSendMessage = (EditText) findViewById(R.id.edt_send_message);
    mTextViewReplyFromServer = (TextView) findViewById(R.id.tv_reply_from_server);
    btn_collect = (Button) findViewById(R.id.btn_send);
    
    btn_collect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String message = "Balls";  // 直接发送触发服务器返回数据的命令
            sendMessage(message);
        }
    });
}

private void sendMessage(final String message) {
    final Handler handler = new Handler(Looper.getMainLooper());  // 确保在主线程更新UI
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            Socket socket = null;
            BufferedReader reader = null;
            OutputStreamWriter writer = null;
            String stringData = "";
            
            try {
                // 替换为你的Python服务器局域网IP
                socket = new Socket("192.168.1.11", 21567);
                
                // 发送数据到服务器,加换行符方便服务器识别结束
                writer = new OutputStreamWriter(socket.getOutputStream());
                writer.write(message + "\n");
                writer.flush();
                
                // 接收服务器返回的数据
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                stringData = reader.readLine();
                
            } catch (IOException e) {
                e.printStackTrace();
                stringData = "Error: " + e.getMessage();
            } finally {
                try {
                    if (reader != null) reader.close();
                    if (writer != null) writer.close();
                    if (socket != null) socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            final String finalData = stringData;
            handler.post(new Runnable() {
                @Override
                public void run() {
                    String currentText = mTextViewReplyFromServer.getText().toString();
                    if (!finalData.trim().isEmpty()) {
                        mTextViewReplyFromServer.setText(currentText + "\n" + finalData);
                    }
                }
            });
        }
    });
    thread.start();
}

额外注意事项

  • 确保Android设备和Python服务器在同一局域网,且服务器IP地址正确;
  • Android 9及以上需在AndroidManifest.xml中添加android:usesCleartextTraffic="true"(测试用);
  • 别忘了在AndroidManifest中申请网络权限:<uses-permission android:name="android.permission.INTERNET"/>;
  • 如需持续累加add的值,要把add变量移到外层循环,否则每次触发都会重置为1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:38:28