简体   繁体   English

Arduino上的TCP问题。 从Python TCP套接字服务器读取字符串

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

I am experimenting with my new arduino UNO Rev 3 and a simple python socket server. 我正在试验新的arduino UNO Rev 3和一个简单的python套接字服务器。 The server code is: 服务器代码为:

##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()

All I'm trying to do is confirm I can communicate with the Arduino and build from there. 我要做的就是确认我可以与Arduino通信并从那里构建。 Here is the relevant Arduino code: 这是相关的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();

}

I keep getting this output: 我不断得到以下输出:

Connected 连接的
Arduino Received: ÿÿÿÿÿÿÿÿÿÿHELLOCLIENT% 收到的Arduino:ÿÿÿÿÿÿÿÿÿÿHELLOCLIENT%
disconnecting. 断开。

Why am I receiving all those padded characters? 为什么我收到所有这些填充字符? I've researched different encoding methods and tried ASCII and UTF-32 but it keeps doing it, what am I missing? 我研究了不同的编码方法,并尝试使用ASCII和UTF-32,但是它一直在执行,我缺少什么?

I'm willing to bet this is your problem: 我愿意打赌这是您的问题:

Whatever your client object is, it's probably either an Arduino Ethernet Client , or one of the many other types with the same interface. 无论您的client对象是什么,它都可能是Arduino 以太网客户端 ,或者是具有相同接口的许多其他类型之一。

If you look at the docs for the read method, it returns: 如果您在文档中查看read方法,它将返回:

The next byte (or character), or -1 if none is available. 下一个字节(或字符);如果没有可用字节,则为-1。

So, when you first connect, you immediately start reading, but nothing has been sent yet, so the first few reads all return -1. 因此,当您第一次连接时,您立即开始阅读,但尚未发送任何内容,因此前几条阅读全部返回-1。

Since this is a char , -1 and 255 are the same value. 由于这是一个char ,因此-1和255是相同的值。 And the character 255, in Latin-1 (and Latin-1-derived character sets) is ÿ , so that's why you're seeing a bunch of ÿ at the start. 在Latin-1(和源自Latin-1的字符集中)中的字符255是ÿ ,因此这就是为什么一开始会看到一堆ÿ的原因。 Changing the encoding will either give you encoding errors or interpret the 255 as some different character, it won't get rid of it. 更改编码会给您带来编码错误,或者将255解释为某些不同的字符,它将无法解决。

So, how do you fix this? 那么,您如何解决呢?


Some client classes (although not all, and the basic Ethernet Client is not one of them) can be put into blocking mode, which means read will wait until there's something to read. 可以将某些客户端类(尽管不是全部,而基本的以太网客户端也不是其中之一)进入阻止模式,这意味着read将一直等到要读取的内容为止。


The Client protocol doesn't actually specify what type read returns. 客户端协议实际上并未指定read返回的类型。 Some Client types return int . 某些客户端类型返回int And in an int , unlike a char , you can distinguish -1 and 255 . int ,与char不同,您可以区分-1255 But once you cast it to char , you throw away the other 3 bytes that and can no longer do so. 但是,一旦将其转换为char ,就会丢弃其他3个字节,并且不再可以这样做。 So, depending on the type you're using, you may be able to do this: 因此,根据您使用的类型,您可以执行以下操作:

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

If you only want to send ASCII text (so only values up to 127 are valid), you know that the -1 will never be an actual character. 如果只想发送ASCII文本(因此只有127个值有效),您知道-1永远不会是实际字符。 In that case, you can just do this: 在这种情况下,您可以执行以下操作:

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

Most client types have a method available , which tells you how many bytes are available to read. 大多数客户端类型都有一个available方法,该方法告诉您有多少字节可读取。 If this returns 0 , wait a bit and try again instead of reading: 如果返回0 ,请稍等,然后重试,而不是读取:

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

Many Arduino samples put this together with a delay(500) or longer at the start of the program, because there's no point wasting time checking for data when the odds are very high that nothing is there yet. 许多Arduino样本在程序开始时将其与delay(500)或更长的时间放在一起,因为当赔率很高而没有任何东西的时候,浪费时间检查数据是没有意义的。


You can add a "start" character to your protocol, just like the "end" character. 您可以在协议中添加“开始”字符,就像“结束”字符一样。 The same way you keep reading until you get a % and then disconnect, you can first keep reading until you get, say, a $ character, throwing away everything up to that point: 继续阅读直到获得%然后断开连接的方式相同,您可以先继续阅读直到获得$字符,然后丢弃直到该点的所有内容:

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