我一直在尝试从我的Yeelight智能灯泡收听多播UDP消息。以固定的间隔,灯泡在IP239.255.255.250
端口1982
上广播其存在。此外,当在同一IP和端口上发送特定请求(found on page 5 - section 3.1)时,灯泡将响应
使用套接字,我试图建立通信。在两台机器(MaOS和Linux)上,下面所示的Python程序运行在RepWorkWork上,但是RISC代码和C++代码也显示在下面(基本上做同样的事情)。Rust程序似乎两次成功接收0字节,然后挂起等待。在C++程序中,^ {< CD3> }函数只是挂起,永远不会返回。
有什么问题吗?为什么只有Python才能成功通信
import socket as s
import struct
sock = s.socket(s.AF_INET, s.SOCK_DGRAM, s.IPPROTO_UDP)
sock.setsockopt(s.IPPROTO_IP, s.IP_ADD_MEMBERSHIP, struct.pack("4sL", s.inet_aton("239.255.255.250"), s.INADDR_ANY))
sock.sendto("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN: \"ssdp:discover\"\r\nST: wifi_bulb\r\n".encode('UTF-8'), ("239.255.255.250", 1982))
sock.recv(4096) # Message received successfully right away from first call
#[macro_use] extern crate log;
use socket2::{Socket, Domain, Type, Protocol, SockAddr};
use std::net::{SocketAddrV4, Ipv4Addr};
fn main() {
env_logger::init();
let yeelight_ip = Ipv4Addr::new(239, 255,255, 250);
let yeelight_port: u16 = 1982;
let socket = Socket::new(
Domain::ipv4(),
Type::dgram(),
Some(Protocol::udp())
).expect("Failed to create socket!");
socket.join_multicast_v4(
&yeelight_ip,
&Ipv4Addr::UNSPECIFIED
).expect("Unable to join multicast broadcast!");
let msg = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN: \"ssdp:discover\"\r\nST: wifi_bulb\r\n";
match socket.send_to(
msg.as_bytes(),
&SockAddr::from(
SocketAddrV4::new(
yeelight_ip,
yeelight_port
)
)
) {
Ok(bytes_sent) => {
// Some lines of debug printing
},
Err(_) => eprintln!("Error broadcasting request for identification!")
loop {
let mut buffer = Vec::with_capacity(1024 * 1024);
let received_bytes = socket
.recv(&mut buffer)
.expect("Unable to receive message!");
debug!("Received {} bytes", received_bytes);
}
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <array>
const std::string msg = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1982\r\nMAN: \"ssdp:discover\"\r\nST: wifi_bulb\r\n";
int main() {
auto yeelight_ip = in_addr();
inet_aton("239.255.255.250", &yeelight_ip);
unsigned int yeelight_port = 1982;
auto sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
std::cerr << "Created socket!" << std::endl;
auto mreq = ip_mreq();
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = yeelight_ip.s_addr;
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) {
std::cerr << "Error joining multicast!" << std::endl;
exit(errno);
}
else {
std::cerr << "Joined multicast!" << std::endl;
}
auto addr = sockaddr_in();
addr.sin_port = yeelight_port;
for (int i = 0; i < 8; i++) addr.sin_zero[i] = 0;
addr.sin_family = AF_INET;
addr.sin_addr = yeelight_ip;
if (sendto(sock, msg.c_str(), msg.length(), 0, (sockaddr*)(&addr), sizeof(addr)) == -1) {
std::cerr << "Error broadcasting request for identification!" << std::endl;
std::cerr << errno << std::endl;
}
else {
std::cerr << "Sent broadcast request for idetification!" << std::endl;
}
while (true) {
std::array<char, 1024 * 1024> buffer;
auto bytes_read = recv(sock, buffer.data(), buffer.size(), 0);
if (bytes_read == -1) {
std::cerr << "Unable to receive message!" << std::endl;
std::cerr << errno << std::endl;
}
else {
std::cerr << "Read " << bytes_read << " bytes..." << std::endl;
std::cout << std::string(buffer.begin(), buffer.begin() + bytes_read) << std::endl;
}
}
return 0;
}
由于Python在幕后很好地实现了转换,因此Python程序可以按预期工作
由于端口的端号错误,C(++)程序无法运行。我忘了我必须使用
addr.sin_port = htons(yeelight_port);
至于Rust程序,我忘记了
with_capacity
只分配了内部缓冲区,但是Vec
仍然是空的。描述为here的解决方案是调用buffer.resize(buffer.capacity(), 0);
相关问题 更多 >
编程相关推荐