为了账号安全,请及时绑定邮箱和手机立即绑定

Python(服务器)在单独的行中从 Java(客户端)接收数据..(TCP)

Python(服务器)在单独的行中从 Java(客户端)接收数据..(TCP)

慕少森 2022-11-30 11:27:15
好的,所以我读了很多问题,但无法弄清楚。我从我的 Android 应用程序收到的数据遇到问题。基本上我想控制伺服。该代码有效,但应用程序发送到服务器的数据是在单独的行中接收的。是的,我知道我需要使用缓冲区,我进行了一些研究,但找不到向我的代码添加缓冲区的方法。此外,我认为我不需要显示我的 Java 代码,因为它只是从按钮点击发送的基本命令(向上、向下等字符串)。...Python Code(Server)...  ctrCmd = ['Up','Down', 'ON', 'OFF']  ...  ...  while True:        print ("Waiting for connection")        tcpCliSock,addr = tcpSerSock.accept()        print ("...connected from :", addr)    try:            while True:                    data = ''                    data = tcpCliSock.recv(BUFSIZE).decode()                    print("This",data)                    if not data:                            print ("No Data",data)                            break                    if data == ctrCmd[0]:                            print("I am here")                            Servomotor.ServoUp()                            print ("Increase: ",Servomotor.cur_X)                            #tcpCliSock.send("Servo Increases".encode())                    if data == ctrCmd[1]:                            Servomotor.ServoDown()                            print ("Decrease: ",Servomotor.cur_X)                            #tcpCliSock.send("Servo Decreases".encode())                    if data == ctrCmd[2]:                            Servomotor.ledOn()                            print ("Led On")                            #tcpCliSock.send("Led On".encode())                    if data == ctrCmd[3]:                            Servomotor.ledOff()                            print ("Led Off")                           # tcpCliSock.send("Led Off".encode())    except KeyboardInterrupt:            Servomotor.close()            GPIO.cleanup()tcpSerSock.close();
查看完整描述

3 回答

?
精慕HU

TA贡献1845条经验 获得超8个赞

试试看:


socket = new java.net.Socket(inetAddress,MainActivity.wifiModulePort);

//read input msg from server

DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

dataOutputStream.writeChars(CMD);

System.out.println(CMD);

dataOutputStream.close();


socket.close();

如果这增加了额外的空间,那么简单的解决方案是继续使用 writeutf 并在服务器端对数据进行子字符串化


socket = new java.net.Socket(inetAddress,MainActivity.wifiModulePort);


//read input msg from server

DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

dataOutputStream.writeUTF(CMD);

System.out.println(CMD);

dataOutputStream.close();


socket.close();

在服务器端:


data = tcpCliSock.recv(BUFSIZE).decode()

data = data[2:]

引用自 Javadoc:


以与机器无关的方式使用修改后的 UTF-8 编码将字符串写入基础输出流。


首先,将两个字节写入输出流,就像使用 writeShort 方法一样,给出后面的字节数。这个值是实际写出的字节数,而不是字符串的长度。在长度之后,字符串的每个字符按顺序输出,使用字符的修改后的 UTF-8 编码。如果没有抛出异常,写入的计数器将增加写入输出流的字节总数。这将至少是 str 长度的两倍,最多是 str 长度的两倍。


查看完整回答
反对 回复 2022-11-30
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

请向服务器提供您的 Android 代码片段(您发送消息的位置)。


当我在本地机器上运行代码时(我没有树莓派控制器,所以我注释掉了某些行):


import sys

import socket

import select


ctrCmd = ['Up', 'Down', 'Left', 'Right', 'Stop', 'Connect']


HOST = ''

PORT = 21567

BUFSIZE = 1024

ADDR = (HOST, PORT)


tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

tcpSerSock.bind(ADDR)


tcpSerSock.listen(1)

print('Waiting for connection')


sendInterval = 1.0  # interval(sec) for sending messages to connected clients


rxset = [tcpSerSock]

txset = []

while True:

    print("Waiting for connection")

    tcpCliSock, addr = tcpSerSock.accept()

    print("...connected from :", addr)


    try:

        while True:

            data = ''

            data = tcpCliSock.recv(BUFSIZE).decode()

            print("This", data)


            if not data:

                print("No Data", data)

                break

            if data == ctrCmd[0]:

                print("I am here")

                # Servomotor.ServoUp()

                print("Increase: ")

                #tcpCliSock.send("Servo Increases".encode())

            if data == ctrCmd[1]:

                # Servomotor.ServoDown()

                print("Decrease: ")

                #tcpCliSock.send("Servo Decreases".encode())

            if data == ctrCmd[2]:

                # Servomotor.ledOn()

                print("Led On")

                #tcpCliSock.send("Led On".encode())

            if data == ctrCmd[3]:

                # Servomotor.ledOff()

                print("Led Off")

               # tcpCliSock.send("Led Off".encode())

    except KeyboardInterrupt:

        # Servomotor.close()

        # GPIO.cleanup()

        print('Exception')

tcpSerSock.close()

在客户端运行以下代码:


import sys

import socket

import time


ctrCmd = [b'Up', b'Down', b'Left', b'Right', b'Stop', b'Connect']


HOST = '127.0.0.1'

PORT = 21567

BUFSIZE = 1024

ADDR = (HOST, PORT)


tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


tcpCliSock.connect(ADDR)

time.sleep(1)

for i in range(len(ctrCmd)):

    tcpCliSock.send(ctrCmd[i])

    time.sleep(1)

data = tcpCliSock.recv(BUFSIZE)

print(data)

tcpCliSock.close()

我最终收到的是:


Waiting for connection

Waiting for connection

...connected from : ('127.0.0.1', 54430)

This Up

I am here

Increase:

This Down

Decrease:

This Left

Led On

This Right

Led Off

This Stop

This Connect

您可能已经注意到,关键是在客户端我发送的不是字符串而是字节数组(b'Up',而不是'Up')。因此,如您所见,服务器端没有问题。


可能在你的 Android 端你需要这样的东西:


String msg = "Up"

byte[] byteArr = msg.getBytes();

更新


好的,我想我知道那里发生了什么。使用套接字的输出流,您只能发送字节数据。它实际上所做的是将您的消息转换为字节数组 (CMD.getBytes())。毫不奇怪,您的服务器正在一步一步、逐字节地接收所有内容。你需要做的是:


    public class MainActivity extends AppCompatActivity {

    //UI Element

    Button btnUp;

    Button btnDown;

    Button btnLedOn;

    Button btnLedOff;

    EditText txtAddress;

    /*TextView message;*/

    Socket myAppSocket = null;

    public static String wifiModuleIp = "";

    public static int wifiModulePort = 0;

    public static String CMD = "0";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        btnUp = (Button) findViewById(R.id.btnUp);

        btnDown = (Button) findViewById(R.id.btnDown);

        btnLedOn = (Button) findViewById(R.id.btnLedOn);

        btnLedOff = (Button) findViewById(R.id.btnLedOff);

        txtAddress = (EditText) findViewById(R.id.ipAddress);

        /*message = (TextView) findViewById(R.id.message);*/


        btnUp.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                getIPandPort();

                CMD = "Up";

                Socket_AsyncTask cmd_increase_servo = new Socket_AsyncTask();

                cmd_increase_servo.execute();

            }

        });

        btnDown.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                getIPandPort();

                CMD = "Down";

                Socket_AsyncTask cmd_increase_servo = new Socket_AsyncTask();

                cmd_increase_servo.execute();

            }

        });

        btnLedOn.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                getIPandPort();;

                CMD = "ON";

                Socket_AsyncTask cmd_led_on = new Socket_AsyncTask();

                cmd_led_on.execute();

            }

        });

        btnLedOff.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                getIPandPort();

                CMD = "OFF";

                Socket_AsyncTask cmd_led_off = new Socket_AsyncTask();

                cmd_led_off.execute();

            }

        });


    }

    public void getIPandPort()

    {

        String iPandPort = txtAddress.getText().toString();


        Log.d("MYTEST","IP String: "+ iPandPort);

        String temp[]= iPandPort.split(":");

        wifiModuleIp = temp[0];

        wifiModulePort = Integer.valueOf(temp[1]);

        Log.d("MY TEST","IP:" +wifiModuleIp);

        Log.d("MY TEST","PORT:"+wifiModulePort);

    }

    public class Socket_AsyncTask extends AsyncTask<Void,Void,Void>

    {

        Socket socket;

        OutputStreamWriter osw;


        @Override

        protected Void doInBackground(Void... params){

            try{


                InetAddress inetAddress = InetAddress.getByName(MainActivity.wifiModuleIp);

                socket = new java.net.Socket(inetAddress,MainActivity.wifiModulePort);

                //read input msg from server

                osw = new OutputStreamWriter(socket.getOutputStream(), 'UTF-8');

                osw.write(CMD, 0, CMD.length());

                out.flush();

                socket.close();

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

            return null;

        }

    }

}


查看完整回答
反对 回复 2022-11-30
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

if not "some string"不会等于 True。您可能想将其更改为:


if data != "" :

    # process here

    pass

您在单独的行中收到数据,可能是因为单独发送。你可以看看我曾经为 TCP 套接字编写的代码。 套接字


也ctrCmd[0]等于'Up'和你的数据内容,正如我在 shell 中看到的那样,是像'U'和这样的字符'P'。所以这条线


if data == ctrCmd[0]:

    print("I am here")

不会运行,因为'Up'不等于'U'.


查看完整回答
反对 回复 2022-11-30
  • 3 回答
  • 0 关注
  • 96 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信