我正在嘗試從嵌入式設備進行 UDP 廣播。平臺是 ESP32;IP 堆疊來自 LwIP。我已經洗掉了所有的錯誤檢查,但是我對 socket() 和 setsockopt() 的呼叫是成功的。我在 sendto() 呼叫中收到 errno 5(I/O 錯誤)。有人可以看到我做錯了什么嗎?
static int iobAnnounce;
const char broadcastEnable = 1;
struct sockaddr_in servaddrAnnounce;
char udp_data[22];
int err;
iobAnnounce = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(iobAnnounce, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
memset(&servaddrAnnounce, 0, sizeof(servaddrAnnounce));
servaddrAnnounce.sin_family = AF_INET;
servaddrAnnounce.sin_port = htons(30303);
servaddrAnnounce.sin_addr.s_addr = htonl(INADDR_BROADCAST);
sendto(iobAnnounce,
udp_data,
22,
0,
(const struct sockaddr *) &servaddrAnnounce,
sizeof(servaddrAnnounce));
感謝您的任何幫助。
編輯
根據@Barmar 的問題,我將代碼修改如下:
err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); // ESP IDF call.
uint32_t subnetBroadcast = ip_info.ip.addr | ~(ip_info.netmask.addr);
servaddrAnnounce.sin_addr.s_addr = (subnetBroadcast);
不幸的是,這并沒有改變行為。我還嘗試對 tcpip_adapter_get_ip_info() 回傳的地址執行 htonl(); 沒有不同。(洗掉的)告密者的輸出是:
I (5354) IOB: iob_task(): tcpip_adapter_get_ip_info() returned ip d456a8c0; netmask 00ffffff; gateway 0156a8c0.
I (5364) IOB: iob_task(): subnetBroadcast is ff56a8c0.
I (5374) IOB: iob_task(): servaddrAnnounce.sin_addr.s_addr is c0a856ff.
uj5u.com熱心網友回復:
來自setsockopt:
“大多數套接字級選項都使用 . 的
int引數optval。對于setsockopt(),該引數應該是非零以啟用布爾選項,或者如果要禁用該選項則為零。”
...所以,broadcastEnable從 achar變為 aint應該這樣做:
const int broadcastEnable = 1;
uj5u.com熱心網友回復:
除了@TedLyngmo 在他的回答中所說的之外,您的代碼還有另一個問題。您沒有subnetBroadcast正確計算。你需要AND在你之前ip_info.ip.addr使用the 的倒數,例如:ip_info.netmask.addr ORip_info.netmask.addr
// uint32_t subnetBroadcast = ip_info.ip.addr | ~(ip_info.netmask.addr);
uint32_t subnetBroadcast = (ip_info.ip.addr & ip_info.netmask.addr) | ~(ip_info.netmask.addr);
uj5u.com熱心網友回復:
嗯,我發現了問題。從 lwip_sendto() 函式:
LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
(IS_SOCK_ADDR_LEN_VALID(tolen) &&
((to != NULL) && (IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))))),
sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;);
失敗的是 IS_SOCK_ADDR_ALIGNED() 測驗——顯然,sockaddr 結構需要在 4 位元組邊界上對齊。而且,顯然,錯誤訊息以某種方式被抑制了,所以我從來沒有看到錯誤。哎呀...
感謝大家的關注。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/488798.html
