Python (сервер), получающий данные от Java (клиент) в отдельных строках .. (TCP) - PullRequest
0 голосов
/ 15 мая 2019

Хорошо, поэтому я прочитал много вопросов и не мог понять это.У меня проблема с данными, полученными из моего приложения для Android.В основном я хочу управлять сервоприводом.Код работает, но данные, отправляемые приложением на сервер, поступают в виде отдельных строк.Да, я знаю, что мне нужно использовать буфер, я немного искал, но не смог найти способ добавить буфер в мой код.Кроме того, я не думаю, что мне нужно показывать свой Java-код, потому что это просто базовые команды (строки типа Up, Down и т. Д.), Отправляемые с помощью нажатия кнопок.

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

enter image description here

Также я не понимаю, почему он говорит, что нет данных, даже когда он показывает полученные данные?Пожалуйста, помогите, я действительно нуб и пытаюсь учиться.СПАСИБО !!

ОБНОВЛЕНИЕ !!После того, как я изменил предложенный декодер (),

enter image description here

    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 enter image description here

ОБНОВЛЕНО 17Мая попытка writeUTF выдает некоторые нулевые данные перед Up (см. Рисунок) enter image description here

Ответы [ 3 ]

1 голос
/ 16 мая 2019

Попробуйте:

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 = новый 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 для символа. Если исключение не выдается, записанный счетчик увеличивается на общее количество байтов, записанных в выходной поток. Это будет в минимум два плюс длина ул, и максимум два плюс трижды длина ул.

0 голосов

if not "some string" не будет равно True.Возможно, вы захотите изменить его на:

if data != "" :
    # process here
    pass

Вы получили данные в отдельной строке, возможно, из-за отправки отдельно.Вы можете посмотреть на мой код, который я когда-то написал для сокета TCP. TCP Socket

Также ctrCmd[0] равно 'Up', и ваши данные, как я вижу в оболочке, представляют собой символы, такие как 'U' и 'P'.Поэтому строка

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

не будет работать, потому что 'Up' не равно 'U'.

0 голосов
/ 15 мая 2019

Пожалуйста, предоставьте свой фрагмент кода Android (куда вы отправляете сообщение) на сервер.

Когда я запускаю код на своем локальном компьютере (у меня нет контроллера Raspberry, поэтому я закомментировал определенные строки):

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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...