2014-10-08 106 views
0

我正在尝试使用新的arduino UNO Rev 3和一个简单的python套接字服务器。服务器代码是:Arduino上的TCP问题。从Python TCP套接字服务器读取字符串

##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,但它一直在做,我错过了什么?

+0

华富首评:“#the你继续读书,直到你得到一个%,然后断开连接,你可以先继续读,直到你得到,比如说,一个$字符,扔掉一切到这一点,以同样的方式双parens将创建一个元素与一个元素“这是行不通的。元组由_commas_创建。有时你碰巧需要parens来消除歧义,但它们不是元组的一部分。 '((ADDR,))'传递一个元素的元组作为参数; '((ADDR))'只是传递'ADDR'。 – abarnert 2014-10-08 00:40:07

+0

Next:'data = str'不会将'data'声明为一个字符串,它会将字符串类型(不是字符串值,表示类型本身的对象)设置为'data'的默认值。使用'recieve.data'并不完全违法,但这很奇怪;当你真正需要的是一个局部变量'data'时,你正在为函数附加一个属性'recieve.data'。 (另外,你拼写“接收”错误。)另外,'leave()'应该做什么? – abarnert 2014-10-08 00:44:07

+0

另外,为什么这个标签C?你有Python代码和Arduino/Wiring代码,但是我没有看到任何C代码。 – abarnert 2014-10-08 00:45:23

回答

1

我敢打赌,这是你的问题:

无论你client对象,它可能是任何一个Arduino Ethernet Client,或许多其他类型具有相同的接口之一。

如果你看一下文档的read方法,它返回:

下一个字节(或字符),或-1,如果没有可用的。

所以,当你第一次连接,你立即开始阅读,但没有任何发送,所以前几个读取全部返回-1。

由于这是char,-1和255是相同的值。并且拉丁字母1(和Latin-1派生的字符集)中的字符255是ÿ,所以这就是为什么你在开始时看到一堆ÿ。改变编码会给你编码错误或将255解释为一些不同的字符,它不会摆脱它。

那么,你如何解决这个问题?


某些客户端类(虽然不是全部,以及基本的以太网客户端是不是其中之一)即可投入阻塞模式,这意味着read会等到有东西可以读。


客户协议实际上并不指定哪些类型read回报。某些客户端类型返回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 */ 
}