簡體   English   中英

Arduino上的TCP問題。 從Python TCP套接字服務器讀取字符串

[英]Issues with TCP on Arduino. Reading Strings from a Python TCP Socket Server

我正在試驗新的arduino UNO Rev 3和一個簡單的python套接字服務器。 服務器代碼為:

##server.py
from socket import *      #import the socket library

#MY FUNCTIONS
def send(data = str):
    conn.send(data.encode())
def recieve():
    recieve.data = conn.recv(BUFSIZE)
    recieve.data = recieve.data.decode()
    return recieve.data

##let's set up some constants
HOST = ''    #we are the host
PORT = 29876    #arbitrary port not currently in use
ADDR = (HOST,PORT)    #we need a tuple for the address
BUFSIZE = 4096    #reasonably sized buffer for data

## now we create a new socket object (serv)
## see the python docs for more information on the socket types/flags
serv = socket( AF_INET,SOCK_STREAM)

##bind our socket to the address
serv.bind((ADDR))    #the double parens are to create a tuple with one element
serv.listen(5)    #5 is the maximum number of queued connections we'll allow
print(" ")
print("Listening")
print(" ")
conn,addr = serv.accept() #accept the connection
print("Connection Established")
send('HELLOCLIENT')
send('%')
leave()

我要做的就是確認我可以與Arduino通信並從那里構建。 這是相關的Arduino代碼:

void loop()
{
    int n =-1;
    while (client.connected())
    {
        n++;
        char recieved = client.read();
        inData[n] = recieved; 

        // Process message when new line character is recieved
        if (recieved == '%')
        {
            Serial.print("Arduino Received: ");
            Serial.print(inData);
            n = -1;
        }
    }
    Serial.println();
    Serial.println("Disconnecting.");
    client.stop();

}

我不斷得到以下輸出:

連接的
收到的Arduino:ÿÿÿÿÿÿÿÿÿÿHELLOCLIENT%
斷開。

為什么我收到所有這些填充字符? 我研究了不同的編碼方法,並嘗試使用ASCII和UTF-32,但是它一直在執行,我缺少什么?

我願意打賭這是您的問題:

無論您的client對象是什么,它都可能是Arduino 以太網客戶端 ,或者是具有相同接口的許多其他類型之一。

如果您在文檔中查看read方法,它將返回:

下一個字節(或字符);如果沒有可用字節,則為-1。

因此,當您第一次連接時,您立即開始閱讀,但尚未發送任何內容,因此前幾條閱讀全部返回-1。

由於這是一個char ,因此-1和255是相同的值。 在Latin-1(和源自Latin-1的字符集中)中的字符255是ÿ ,因此這就是為什么一開始會看到一堆ÿ的原因。 更改編碼會給您帶來編碼錯誤,或者將255解釋為某些不同的字符,它將無法解決。

那么,您如何解決呢?


可以將某些客戶端類(盡管不是全部,而基本的以太網客戶端也不是其中之一)進入阻止模式,這意味着read將一直等到要讀取的內容為止。


客戶端協議實際上並未指定read返回的類型。 某些客戶端類型返回int int ,與char不同,您可以區分-1255 但是,一旦將其轉換為char ,就會丟棄其他3個字節,並且不再可以這樣做。 因此,根據您使用的類型,您可以執行以下操作:

int recieved = client.read();
if (recieved == -1) continue;
inData[n] = (char)recieved;

如果只想發送ASCII文本(因此只有127個值有效),您知道-1永遠不會是實際字符。 在這種情況下,您可以執行以下操作:

char recieved = client.read();
if (recieved == -1) continue;

大多數客戶端類型都有一個available方法,該方法告訴您有多少字節可讀取。 如果返回0 ,請稍等,然后重試,而不是讀取:

if (!client.available()) {
    delay(200);
    continue;
}

許多Arduino樣本在程序開始時將其與delay(500)或更長的時間放在一起,因為當賠率很高而沒有任何東西的時候,浪費時間檢查數據是沒有意義的。


您可以在協議中添加“開始”字符,就像“結束”字符一樣。 繼續閱讀直到獲得%然后斷開連接的方式相同,您可以先繼續閱讀直到獲得$字符,然后丟棄直到該點的所有內容:

while (client.connected()) {
    char received = client.read();
    if (received == '$') break;
}
while (client.connected()) {
    /* your original code here */
}

暫無
暫無

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

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