我正在试验新的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 Ethernet Client,或者是具有相同接口的许多其他类型之一。
如果查看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 */
}