Lost broadcast packets.
-
Hi,
I have a strange behavior in my C application. If have created to simple test apps to demonstrate the error.I have to devices:
1. A Fedore 5 Intel PC with GCC 4.1.1 and kernel 2.6.20-1.2320.fc5smp
2. A single chip computer with STLinux with sh4-linux-gcc 4.1.1 and kernel 2.6.17.14_stm22_0038Both systems are connected by two wireless links. Link one in the net 192.168.1.0 and link two in the net 192.168.22.0.
I wrote an application that detects broken links. It is similar to OLSR, but has faster reaction times.In the test application I have a receiver-application running on the Fedora PC. It opens the socket on port 1980 and checks in an endless-loop for incoming packets.
On the STLinux device I have a sender-application that send UDP packets to one broadcast address, waits 200ms, sends an UDP packet to the other BC-address waits 200ms and starts again by sending the first BC. (Endless-loop). To socket to send the packets is also on 1980.The problem is now, that on the PC (receiver) half of the packets sent to 192.168.22.255 are ignored by my application. This means a 'recvfrom' does not receive them. However I see the packets arriving with tcpdump!!! So somewhere between the TCP-stack and my application the packets are lost.
I have realized, that when the senders socket is not on port 1980, but on port 1981 it works. But I would prefer that my application works with one port (like others do).
Any suggestion why this happens?
Here is my code:
Receive application on the Fedora PC:
#include <string.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h> #include <netdb.h> int nw_socket_fd; struct sockaddr_in nw_sock_addr; char buffer[1024]; struct sockaddr_in from_addr; int from_len; int main() { int val = 1; // socket for nw com bzero( &nw_sock_addr, sizeof(nw_sock_addr)); nw_sock_addr.sin_family = AF_INET; nw_sock_addr.sin_addr.s_addr = htons(INADDR_ANY); nw_sock_addr.sin_port = htons(1980); nw_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); if ( nw_socket_fd < 0 ) { printf("Could not open network socket.\n"); exit(1); } // allow broadcasting setsockopt(nw_socket_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)); if (bind(nw_socket_fd, (struct sockaddr *) &nw_sock_addr, sizeof(struct sockaddr)) ) { printf("Could not bind for network.\n"); exit(1); } while (1) { char* from_name; int ret; memset( buffer, '\0', sizeof(buffer) ); ret = recvfrom( nw_socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&from_addr, &from_len); from_name = inet_ntoa(from_addr.sin_addr); printf("Msg received from: %s\n", from_name); } return(0); }
I compiled it with:
gcc -O0 -o bc_receive bc_receive.c
The sender-application on the STLinux board:
#include <string.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h> #include <netdb.h> #include <time.h> #include <sys/time.h> int main() { int nw_socket_fd; struct sockaddr_in nw_sock_addr; struct sockaddr_in to_addr1; struct sockaddr_in to_addr2; int from_len; int val; char buf[1]; int buf_len; struct timespec delay; unsigned char cntr; val = 1; // socket for nw com bzero( &nw_sock_addr, sizeof(nw_sock_addr)); nw_sock_addr.sin_family = AF_INET; nw_sock_addr.sin_addr.s_addr = htons(INADDR_ANY); nw_sock_addr.sin_port = htons(1980); nw_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); if ( nw_socket_fd < 0 ) { printf("Could not open network socket.\n"); exit(1); } // allow broadcasting setsockopt(nw_socket_fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)); if (bind(nw_socket_fd, (struct sockaddr *) &nw_sock_addr, sizeof(struct sockaddr)) ) { printf("Could not bind for network.\n"); exit(1); } cntr = 0; buf_len = sizeof(buf); delay.tv_sec = 0; delay.tv_nsec = 200000000; to_addr1.sin_family = AF_INET; //to_addr.sin_addr.s_addr = htons(INADDR_ANY); inet_aton("192.168.1.255", &(to_addr1.sin_addr)); to_addr1.sin_port = htons(1980); to_addr2.sin_family = AF_INET; //to_addr.sin_addr.s_addr = htons(INADDR_ANY); inet_aton("192.168.22.255", &(to_addr2.sin_addr)); to_addr2.sin_port = htons(1980); while (1) { buf[1] = (char) cntr; if (cntr == 254) cntr = 0; else cntr++; if (sendto( nw_socket_fd, buf, buf_len, 0, (struct sockaddr *)&to_addr1, sizeof(struct sockaddr)) < 0 ) { printf("Error: Could not send heartbeat 1.\n"); } else printf("HB 1 sent.\n"); nanosleep(&delay, NULL); buf[1] = (char) cntr; if (cntr == 254) cntr = 0; else cntr++; if (sendto( nw_socket_fd, buf, buf_len, 0, (struct sockaddr *)&to_addr2, sizeof(struct sockaddr)) < 0 ) { printf("Error: Could not send heartbeat 2.\n"); } else printf("HB 2 sent.\n"); nanosleep(&delay, NULL); } return(0); }
Complied with
sh4-linux-gcc -Wall -ggdb -o bc_send bc_send.c
.
The output from the sender is:
root@stb7109:~/frank_stuff# ./bc_send
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
HB 1 sent.
HB 2 sent.
...The output from the receiver is:
[rmfleipo@kontron986 bc_test]$ ./bc_receive
Msg received from: 0.0.0.0
Msg received from: 192.168.1.5
Msg received from: 192.168.22.2
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.22.2
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.1.5
Msg received from: 192.168.22.2
Msg received from: 192.168.1.5
Msg received from: 192.168.22.2
Msg received from: 192.168.1.5
...And remember: When I changed at the sender:
nw_sock_addr.sin_port = htons(1980);
to
nw_sock_addr.sin_port = htons(1981);
it works.
The problem is that I also have non-broadcast messages and a uncertain number of devices that my run my application. So I prefer to stick to one port.
Thanks for helping.
-
May be you should try a portnumber which is _not_ reserved by the IANA http://www.iana.org/assignments/port-numbers
-
I changed that, but it has no effects.
-
nw_sock_addr.sin_addr.s_addr = htons(INADDR_ANY);
maybe that's the problem in your receiver application^^
try to receive only from one dedicated address, not INADDR_ANY.
anyway, udp packets are allowed to be thrown away by the protocol stack if no one reads them in time.