I'm trying to send a multicast message via a socket, then receive responses from devices on the network that respond.
The message sends successfully, and I can see the responses targeting the source IP address on wireshark, but attempting to call recvfrom
just results in timeouts.
I have tried many combinations of socket options, bindings, but I've been unable to get past a timeout on recvfrom
.
My current code (sending and receiving):
// Ethernet/IP Encapsulation Header
struct __attribute__((__packed__)) EnipEncapHeader
{
uint16_t command;
uint16_t length;
uint32_t session_handle;
uint32_t status;
uint64_t ctx_64;
uint32_t options;
};
int main() {
// initialize winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
// create a udp socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
printf("ERROR opening socket");
return 1;
}
// set the broadcast flag
int broadcastEnable = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));
// Construct the message
struct EnipEncapHeader header;
header.command = 0x63;
header.length = 0x0000;
header.session_handle = 0x00000000;
header.status = 0x0000;
header.ctx_64 = (uint64_t)0;
header.options = 0x0000;
// send to 255.255.255.255 on port 44818
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
servaddr.sin_port = htons(44818);
// send the packet
int rc = sendto(sockfd, (const char*)&header, sizeof(header), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (rc < 0) {
printf("ERROR sending packet, %d, %d", rc, WSAGetLastError());
return 1;
}
// clear the broadcast flag
broadcastEnable = 0;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));
// set the timeout to 5 seconds
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
// bind the socket to any address
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
// recieve from any address on the socket
struct sockaddr_in from;
int fromlen = sizeof(from);
char buf[1024];
rc = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
if (rc < 0) {
printf("ERROR recieving packet, %d, %d", rc, WSAGetLastError());
return 1;
}
else {
printf("Received %d bytes from %s:%d", rc, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
}
return 0;
}
This code results in the following:
ERROR recieving packet, -1, 10060
Winsock Error 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.