[英]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
不同,您可以區分-1
和255
。 但是,一旦將其轉換為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.