while 循环内分配的全局变量在循环外不可用

Global variable assigned inside while loop not available outside the loop

我正在使用 ESP8266 WiFi 芯片呼叫 api。我正在声明一个全局变量以将服务器发送的令牌分配给它。变量赋值是在 while 循环内进行的。在这个循环中,我正在读取回复 "the token" 的内容并将其保存在全局变量中。 但是当我打印出 while 循环外的结果时,变量是空的。但在循环内部它不是。

String deviceToken;

WiFiClient client;

  if (!client.connect(hostIp, 80)){
    Serial.println("Connection to server failed.");
    Serial.print(client.connect(hostIp, 80));
    return;
  }

    String authURL = "/api/";
      authURL += "startauth/";
      authURL += serialValue;
      Serial.print("Requesting URL: ");
      Serial.println(authURL);

      // This will send auth request to the server
      client.print(String("GET ") + authURL + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" + 
                   "Connection: close\r\n\r\n");
     unsigned long timeout = millis();
     while (client.available() == 0) {
        if (millis() - timeout > 5000) {
          Serial.println(">>> Client Timeout !");
          client.stop();
          return;
        }
     }
    // Read Auth reply from server and print them to Serial
      while(client.available()){
        String token = client.readStringUntil('\r');
        deviceToken = token;
        writeDeviceToken(token.c_str());  //Function to write data in eeprom
        Serial.print(deviceToken); //NOT EMPTY
      }

      Serial.print("Device Token:" + deviceToken);  //EMPTY VARIABLE

在您的 while 循环中,您逐行遍历 HTTP header 和数据并每次覆盖 deviceToken。这没关系,除了每行以 \r\n 结尾而不仅仅是 \r -(另外,您可能只想将令牌写入 eeprom,而不是每个 header)。

所以读取的最后一个标记是单个 \n,然后将其放入 deviceToken。您将需要在每行之后读取额外的字节。

另一种方法是读取直到到达 \r\n\r\n(header 块的末尾),然后读取大小(28 十六进制 - 这是一个 chunked transfer),然后然后你可以读取并存储你想要的令牌。否则,您的令牌将是最后一个 0,或者它后面的换行符。

还要记住,不能保证回复总是被分块(在这种情况下这实际上很奇怪),您也应该为 'normal' 回复做好准备。

解决此问题的一个简单方法是发送 HTTP/1.0 请求而不是 HTTP/1.1(只要该服务器支持)。由于 HTTP/1.0 不会 support/allow 分块传输,您将始终在回复中看到 'clean' deviceToken

感谢 Danny_ds 的指导,我得以解决我的问题,并想在这里分享工作代码作为参考。

// Read Auth reply from server and print them to Serial
  while(client.available()){

      char c = client.read(); 
      response += c;
  }
   String testStatus = response;
   if((strstr(testStatus.c_str(),"HTTP/1.1 500")) != NULL) {
    Serial.println("Found reponse 500");
    return;

   } else if ((strstr(testStatus.c_str(),"HTTP/1.1 200")) != NULL) {
      Serial.println("Found reponse 200");
      //Grabing the token after the header
      String token = response.substring(response.indexOf("\r\n\r\n") + 8 );
      //Removing the \r in end of token
      token.remove(40);
      deviceToken = token;
      writeDeviceToken(deviceToken.c_str());
      delay(500);
      Serial.print("Device Token:" + deviceToken);
      return;
   }