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;
}
我正在使用 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;
}