簡體   English   中英

Python(Server)從Java(client)接收數據,在單獨的行中..(TCP)

[英]Python(Server) receiving Data from Java(client) In separate lines.. (TCP)

好的,所以我讀了許多問題,無法解決。 我從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();

在此處輸入圖片說明

我也不明白為什么即使顯示收到的數據也說沒有數據? 請幫助我真的是菜鳥,正在嘗試學習。 謝謝!!

UPDATE! 在我更改了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代碼的輸出 在此處輸入圖片說明

更新17 May我嘗試了writeUTF,它在Up之前給出了一些空數據(參見圖像) 在此處輸入圖片說明

試試看:

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並在服務器端對數據進行子字符串化

套接字=新的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編碼,依次輸出字符串的每個字符。 如果未引發異常,則寫入的計數器將增加寫入輸出流的字節總數。 這將是至少2加str的長度,最多2加3的str的長度。

請您向您的服務器提供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;
        }
    }
}

if not "some string"將不等於True。 您可能需要將其更改為:

if data != "" :
    # process here
    pass

您在單獨的行中接收到數據,這可能是因為單獨發送。 您可以看一下我曾經為TCP套接字編寫的代碼。 TCP套接字

另外ctrCmd[0]等於'Up' ,我在shell中看到的數據內容是'U''P''U'字符。 所以線

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

將不會運行,因為'Up'不等於'U'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM