【问题标题】:Python(Server) receiving Data from Java(client) In separate lines.. (TCP)Python(服务器)从Java(客户端)接收数据在单独的行中..(TCP)
【发布时间】:2019-05-15 10:19:06
【问题描述】:

好的,所以我阅读了很多问题,但无法弄清楚。我从我的 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();

我也不明白为什么它显示没有数据,即使它显示收到的数据? 请帮助我真的是一个菜鸟,正在努力学习。 谢谢!!

更新!! 在我更改了 decode() 建议后,

    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;

        @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

                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                dataOutputStream.writeBytes(CMD);
                System.out.println(CMD);
                dataOutputStream.close();

                socket.close();
            }catch (UnknownHostException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();}
            return null;
        }
    }
}

Android 代码的输出

5 月 17 日更新 我试过 writeUTF 它在 Up 之前给出了一些空数据(见图)

【问题讨论】:

  • 您好,您的缓冲区大小是多少?
  • 嘿!..是1024
  • 如果您尝试将缓冲区大小增加到 2048?
  • 是的,我做到了,仍然是同样的事情,当我在 python 2 中写回相同的代码时,它运行良好,但是在 python 3 或发生的事情之后,它给出了这种输出,它给出了正确的如果我在我的 Android 应用程序上单击“向上”按钮 5-10 次,则输出。但随后它发送多个输入并且伺服移动额外的旋转。

标签: java android python sockets


【解决方案1】:

试一试:

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 的长度,最多两加上三倍 长度。

【讨论】:

  • 太棒了!据我了解,它现在可以在开始时接收带有一些噪音的整个字符串,对吗?我们已经接近解决方案
  • 终于!!!!它可以工作..我尝试了 writeChars() 它没有用,但是客户端的 writeutf() 和服务器上的 data[:2] 对我来说效果很好,它正确地接受了输入(是的,空值仍然存在!).. ..虽然我认为这在网络方面效率不高,但它就像一个魅力!!..你是了不起的人..Ping我@socialsubscriptionss@gmail.com。
  • 雅虎!是的,当然,可以应用改进,但目标是通过仅更改几行初始代码来提出解决方案。最好的办法是在服务器端使用 select () 并使用 for each in socket 而不是第二个无限循环。很高兴听到它成功了!
【解决方案2】:

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

if data != "" :
    # process here
    pass

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

另外ctrCmd[0] 等于'Up',我在shell 中看到的数据内容是'U''P' 之类的字符。所以这条线

if data == ctrCmd[0]:
    print("I am here")

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

【讨论】:

  • 这没有太大区别我没有遇到 if 循环的问题,我的主要问题是数据单独发送,我的 android 应用程序中有一个控制台输出,它确认我正在发送的数据一次全部发送。接收器(Python 使用 TCP)以便单独接收数据,我需要一种在一个缓冲区中一起接收数据的方法,我需要它的代码我到处查找没有人建议清楚地暗示如何在 RPI 套接字中使用缓冲区使用 Android。
  • 你试过调试数据内容吗?里面有'\n'吗?
  • 是的,我检查了 \n,并且我发送的数据是来自 Android 的“Up”,但是使用 TCP 的 Python 接收数据是分开的,这就是这个问题的含义,您可以检查 Ive 的更新把我的输出图像。
【解决方案3】:

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

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

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();

更新

好的,我想我知道那里发生了什么。使用 Socket 的输出流,您只能发送字节数据。它实际上所做的是将您的消息转换为字节数组 (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;
        }
    }
}

【讨论】:

  • 增加缓冲区并没有做任何事情,而是增加了我的应用程序上的向上按钮的点击次数。您的回答也是肯定的,但是如何删除数据后的空格?有什么帮助吗?
  • 我按照你说的做了,但这次它给出了相同的输出显示“No Data b'”
  • 没有 decode() 它给出的数据输出为 -> b'U' 然后 b'p' 在下一行,最后是 b'',然后按几次向上按钮后给出b'Up' 不起作用,因为我的 ctrCmd 没有 b'Up' 它只有 'Up' 这就是为什么我使用 Decode 来摆脱那个 'b'
  • 查看更新后的答案。这能解决您的问题吗?
  • 我是否将其复制粘贴到我的应用程序的 try { } 块中?我复制粘贴,发现我的python现在没有接收数据它没有数据,我尝试更改python代码但没有成功。
猜你喜欢
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多