ESP8266 - 使用本地 mDNS 地址时 HTTPClient 不工作
ESP8266 - HTTPClient not working when using local mDNS address
我的本地网络服务器有 mDNS - http://android.local:8182
我想通过使用 ESP8266HTTPClient 库中的 HTTPClient class 将它与 ESP8266 一起使用。代码如下:
HTTPClient http;
http.begin("http://android.local:8182");
http.addHeader("values.json", "text/json");
int code = http.POST(jsonStr);
Log(DATA, "HTTP code: " + String(code));
Log(DATA, "Response: " + http.getString());
但它总是returns -1 代码。当我从字面上复制粘贴 url 到我的电脑网络浏览器时,它起作用了。我尝试用我的服务器的 IP 地址替换 "android.local" 并且它有效,但不是 mDNS 地址。谁能告诉我如何让它正常工作?
Windows、macOS 和 Linux 都 运行 在比 ESP8266 更强大的计算机上。虽然常规 DNS 和 mDNS 几乎是相同的协议,但它们的使用方式不同并且分别实现。事实上,Windows和Linux在不安装额外软件的情况下不支持mDNS是很常见的(Windows下的"Bonjour"和Linux下的"avahi") .
您可以通过两种方式在 ESP8266 上使用 Arduino SDK 实现这一点。
无论哪种方式,您都需要将 android.local
解析为其 IP 地址,然后重写 URL 以包含 IP 地址而不是主机名。
不幸的是,ESP8266 mDNS 库不支持直接将主机名解析为 IP 地址,因此这会有点扭曲。
第一种方式:如果正在做广告的设备android.local
提供了"http"、"tcp"的mDNS服务记录,并提供了IP地址和端口号(8182) advertisement,然后可以使用ESP8266mDNS库查询服务记录。
您的代码将如下所示:
// your other necessary #include's first
#include <ESP8266mDNS.h>
#define HOSTNAME "the name of this ESP8266"
#define TARGET_HOSTNAME "android"
bool resolve_mdns_service(char* service_name, char* protocol, char* desired_host, IPAddress* ip_addr, uint16_t *port_number) {
Serial.println("Sending mDNS query");
int n = MDNS.queryService(service_name, protocol);
Serial.printf("mDNS query got %d results\n", n);
if(n == 0) {
Serial.println("no services found");
} else {
for (int i = 0; i < n; ++i) {
#ifdef DEBUG
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i));
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
#endif
if(strcmp(MDNS.hostname(i).c_str(), desired_host) == 0) {
*ip_addr = MDNS.IP(i);
*port_number = MDNS.port(i);
return true;
}
}
}
return false;
}
void setup() {
// get WiFi setup first
if(!MDNS.begin(HOSTNAME))
Serial.println("Error setting up MDNS responder!");
else
Serial.println("mDNS responder started");
IPAddress server_ip;
uint16_t port_number;
if(resolve_mdns_service("http", "tcp", TARGET_HOSTNAME, &server_ip, &port_number)) {
Serial.printf("got an answer for %s.local!\n", TARGET_HOSTNAME);
Serial.println(server_ip);
Serial.println(port_number);
} else {
Serial.printf("Sorry, %s.local not found\n", TARGET_HOSTNAME);
}
}
这仅在您的设备通告 "http"、"tcp" mDNS 服务记录时有效。
如果没有,最好的办法是使用第三方库。
在这种情况下,您需要按照说明在您的项目中安装此库:
https://github.com/madpilot/mDNSResolver
您的代码将如下所示:
// your other necessary #include's first
#include <mDNSResolver.h>
#define TARGET_HOSTNAME "android"
WiFiUDP udp;
mDNSResolver::Resolver resolver(udp);
void setup() {
// get WiFi setup first
Serial.printf("Attempting to resolve %s\n", TARGET_HOSTNAME);
IPAddress answer = resolver.search(TARGET_HOSTNAME);
if(answer == IPADDR_NONE) {
Serial.println("no answer found");
} else {
Serial.println("Gotta result!");
Serial.println(answer);
}
}
第一种方法需要更多代码,但不需要外部第 3 方库,并且并非在所有情况下都有效。
获得 IP 地址后,您可以使用它来组合 URL 您传递给 http.begin()
并从那里继续。
mDNS 是一个 "unreliable" 协议 - 它不保证您会得到答案,或所有答案。因此,如果您在第一种方法中定义 DEBUG
,则每次执行时您可能会看到略有不同的结果集。如果您的代码无法解析主机名,您可能需要在放弃之前重试 2-3 次。
我的本地网络服务器有 mDNS - http://android.local:8182 我想通过使用 ESP8266HTTPClient 库中的 HTTPClient class 将它与 ESP8266 一起使用。代码如下:
HTTPClient http;
http.begin("http://android.local:8182");
http.addHeader("values.json", "text/json");
int code = http.POST(jsonStr);
Log(DATA, "HTTP code: " + String(code));
Log(DATA, "Response: " + http.getString());
但它总是returns -1 代码。当我从字面上复制粘贴 url 到我的电脑网络浏览器时,它起作用了。我尝试用我的服务器的 IP 地址替换 "android.local" 并且它有效,但不是 mDNS 地址。谁能告诉我如何让它正常工作?
Windows、macOS 和 Linux 都 运行 在比 ESP8266 更强大的计算机上。虽然常规 DNS 和 mDNS 几乎是相同的协议,但它们的使用方式不同并且分别实现。事实上,Windows和Linux在不安装额外软件的情况下不支持mDNS是很常见的(Windows下的"Bonjour"和Linux下的"avahi") .
您可以通过两种方式在 ESP8266 上使用 Arduino SDK 实现这一点。
无论哪种方式,您都需要将 android.local
解析为其 IP 地址,然后重写 URL 以包含 IP 地址而不是主机名。
不幸的是,ESP8266 mDNS 库不支持直接将主机名解析为 IP 地址,因此这会有点扭曲。
第一种方式:如果正在做广告的设备android.local
提供了"http"、"tcp"的mDNS服务记录,并提供了IP地址和端口号(8182) advertisement,然后可以使用ESP8266mDNS库查询服务记录。
您的代码将如下所示:
// your other necessary #include's first
#include <ESP8266mDNS.h>
#define HOSTNAME "the name of this ESP8266"
#define TARGET_HOSTNAME "android"
bool resolve_mdns_service(char* service_name, char* protocol, char* desired_host, IPAddress* ip_addr, uint16_t *port_number) {
Serial.println("Sending mDNS query");
int n = MDNS.queryService(service_name, protocol);
Serial.printf("mDNS query got %d results\n", n);
if(n == 0) {
Serial.println("no services found");
} else {
for (int i = 0; i < n; ++i) {
#ifdef DEBUG
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i));
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
#endif
if(strcmp(MDNS.hostname(i).c_str(), desired_host) == 0) {
*ip_addr = MDNS.IP(i);
*port_number = MDNS.port(i);
return true;
}
}
}
return false;
}
void setup() {
// get WiFi setup first
if(!MDNS.begin(HOSTNAME))
Serial.println("Error setting up MDNS responder!");
else
Serial.println("mDNS responder started");
IPAddress server_ip;
uint16_t port_number;
if(resolve_mdns_service("http", "tcp", TARGET_HOSTNAME, &server_ip, &port_number)) {
Serial.printf("got an answer for %s.local!\n", TARGET_HOSTNAME);
Serial.println(server_ip);
Serial.println(port_number);
} else {
Serial.printf("Sorry, %s.local not found\n", TARGET_HOSTNAME);
}
}
这仅在您的设备通告 "http"、"tcp" mDNS 服务记录时有效。
如果没有,最好的办法是使用第三方库。
在这种情况下,您需要按照说明在您的项目中安装此库:
https://github.com/madpilot/mDNSResolver
您的代码将如下所示:
// your other necessary #include's first
#include <mDNSResolver.h>
#define TARGET_HOSTNAME "android"
WiFiUDP udp;
mDNSResolver::Resolver resolver(udp);
void setup() {
// get WiFi setup first
Serial.printf("Attempting to resolve %s\n", TARGET_HOSTNAME);
IPAddress answer = resolver.search(TARGET_HOSTNAME);
if(answer == IPADDR_NONE) {
Serial.println("no answer found");
} else {
Serial.println("Gotta result!");
Serial.println(answer);
}
}
第一种方法需要更多代码,但不需要外部第 3 方库,并且并非在所有情况下都有效。
获得 IP 地址后,您可以使用它来组合 URL 您传递给 http.begin()
并从那里继续。
mDNS 是一个 "unreliable" 协议 - 它不保证您会得到答案,或所有答案。因此,如果您在第一种方法中定义 DEBUG
,则每次执行时您可能会看到略有不同的结果集。如果您的代码无法解析主机名,您可能需要在放弃之前重试 2-3 次。