Home/Support/Support Forum/Does UDP socket need heartbeat message
Welcome to Digi Forum, where you can ask questions and receive answers from other members of the community.

Does UDP socket need heartbeat message

+1 vote
Hello,

I am running UDP protocol on RCM3315 and the task is to listen on one UDP Multicast Port and IP and send to another UDP Multicast Port and IP. I am also allowing for Telnet connection on another socket.

The Rabbit board is on a switch which handles multicast traffic.
The board is assigned a static IP address on the switch.

The following code is running tcp_tick and my_tick() which handles the states of connection. The switch cases handle send and receive port states.

Why do I need to use udp_send() with a heartbeat message to be able to receive packets?
See under "// Check the timer--if it has expired, send another heartbeat packet" comment.

If I comment the heartbeat message out, the receive interrupts but reads all zeroes.

Any idea of what the heartbeat message doing?
Code:
void main() { unsigned int connectionDelayCnt = 0, statusDelayCnt = 0; io_init(); memset(state, 0, sizeof(state)); while (1) { costate //TCPIP { tcp_listen (&socket, TCPIPPORT, 0, 0, NULL, 0); while (!sock_established(&socket) && sock_bytesready(&socket) == -1) { remoteConnection = 0; yield; } while (sock_established(&socket)) { if (!remoteConnection) { tcpipCommandCounter = 0; delay (100); remoteConnection = 1; tcpipCommandReceived = 1; //must fool TransmitData routine sprintf (outputBuf, "%s", commandPrompt); TransmitTCPData(prompt); tcpipCommandReceived = 0; } ReadTCPIPData(); yield; } sock_close (&socket); } costate { if (pd_havelink(0) != 0) // check if link exists // Drive the TCP/IP stack tcp_tick(NULL); // Drive UDP state machine my_tick(); } costate //Send Message approximately every second { if (++statusDelayCnt == 5000) { statusDelayCnt = 0; sendmsg(); } } costate //CONNECTION { if (++connectionDelayCnt == 500) { connectionDelayCnt = 0; SetConnection(); } } } // end while (1) } // end main() // Do processing on the multicast sockets xmem void my_tick(void) { auto int i; auto int retval; auto longword remip; auto word remport; auto char ipbuf[16]; unsigned long msg_id; // Process socket 0 (Multicast Write) switch (state[0].state) { case MCAST_OPENING: // Open the multicast socket retval = udp_extopen(&state[0].sock, IF_ETH0, myFlashArray.port_udp_multi_write, inet_addr (myFlashArray.ip_udp_multi_write), myFlashArray.port_udp_multi_write, NULL, 0, 0); if (retval == 0) { // Error opening the socket printf("Error opening socket %d!\n", 0); state[0].state = MCAST_CLOSED; } else { // Set the interval timer, and advance to the next state state[0].timer = set_timeout(conf[0].interval); state[0].state = MCAST_CLOSING; } break; case MCAST_CLOSING: sock_close(&state[0].sock); state[0].state = MCAST_CLOSED; break; case MCAST_CLOSED: // Do nothing break; default: // There is no transition to a state other than the ones listed // above. So, if we reach this "state", then something is // dreadfully wrong. printf("Error in state machine! Not in a known state...\n"); exit(1); } // Process socket 1 (Multicast Read) switch (state[1].state) { case MCAST_OPENING: // Open the multicast socket retval = udp_extopen(&state[1].sock, IF_ETH0, myFlashArray.port_udp_multi_read, inet_addr (myFlashArray.ip_udp_multi_read), myFlashArray.port_udp_multi_read, NULL, 0, 0); if (retval == 0) { // Error opening the socket printf("Error opening socket %d!\n", 1); state[1].state = MCAST_CLOSED; } else { // Set the interval timer, and advance to the next state state[1].timer = set_timeout(conf[1].interval); state[1].state = MCAST_RUNNING; } break; case MCAST_RUNNING: // Check for any incoming datagrams retval = udp_recvfrom(&state[1].sock, bufferUDP, strlen(bufferUDP), &remip, &remport); if (retval < -1) { // Error reading from the socket printf("Error reading from socket %d!\n", 1); state[1].state = MCAST_CLOSING; } else if (retval >= 0) { // NULL terminate the buffer and print a message bufferUDP[retval] = '\0'; inet_ntoa(ipbuf, remip); printf("Received on socket %d from %s port %u:\n", 1, ipbuf, remport); printf("%02X%02X%02X%02X%02X%s\n", bufferUDP[0], bufferUDP[1], bufferUDP[2], bufferUDP[3], bufferUDP[4], &bufferUDP[5]); msg_id = ((0x000000FF & bufferUDP[0]) << 24) | ((0x000000FF & bufferUDP[1]) << 16) | ((0x000000FF & bufferUDP[2]) << 8) | (0x000000FF & bufferUDP[3]); if (msg_id == myFlashArray.cmd_query_id) { outputBufUDP[0] = (0xFF000000 & myFlashArray.query_resp_id) >> 24; outputBufUDP[1] = (0x00FF0000 & myFlashArray.query_resp_id) >> 16; outputBufUDP[2] = (0x0000FF00 & myFlashArray.query_resp_id) >> 8; outputBufUDP[3] = 0x000000FF & myFlashArray.query_resp_id; outputBufUDP[4] = bufferUDP[4]; //cmd/query enumerator if (bufferUDP[4] == 0x01) { sprintf(&outputBufUDP[5], "%s", myFlashArray.unitid); udp_sendto(&state[0].sock, outputBufUDP, strlen(&outputBufUDP[5]) + 6, inet_addr(myFlashArray.ip_udp_multi_write), myFlashArray.port_udp_multi_write); } if (bufferUDP[4] == 0x02) { sprintf(&outputBufUDP[5], "%s", myFlashArray.serialnum); udp_sendto(&state[0].sock, outputBufUDP, strlen(&outputBufUDP[5]) + 6, inet_addr(myFlashArray.ip_udp_multi_write), myFlashArray.port_udp_multi_write); } } } // Check the timer--if it has expired, send another heartbeat packet if (chk_timeout(state[1].timer)) { state[1].timer = set_timeout(conf[1].interval); sprintf(bufferUDP, "Heartbeat packet #%ld on socket %d\n", state[1].pkts_sent, 1); retval = udp_send(&state[1].sock, bufferUDP, strlen(bufferUDP)+1); state[1].pkts_sent += 1; if (retval < 0) { printf("Error sending on socket %d!\n", 1); state[1].state = MCAST_CLOSING; } } break; case MCAST_CLOSING: sock_close(&state[1].sock); state[1].state = MCAST_CLOSED; break; case MCAST_CLOSED: // Do nothing break; default: // There is no transition to a state other than the ones listed // above. So, if we reach this "state", then something is // dreadfully wrong. printf("Error in state machine! Not in a known state...\n"); exit(1); } }
asked Feb 25 in Rabbit Software by dbabayev New to the Community (8 points)

Please log in or register to answer this question.

1 Answer

+1 vote
Some thoughts:
* Instead of your loops, you can use "waitfor(DelayMs(1000));" to introduce a delay in your costates.
* Your multicast write socket needs a MCAST_RUNNING state where you just keep it open, maybe checking the status and reopening it if it closes for some reason (but there shouldn't be any reason for it to close). It's possible that the repeated open/close sequence contributes to your problems, especially if the IP address matches the one used for your multicast read socket.
* BIG BUG: your udp_recvfrom() should be using sizeof(bufferUDP) instead of strlen(bufferUDP) as the buffer size parameter.
* I don't believe it's necessary to send a heartbeat message. That code is in the sample so there's multicast traffic if your running the sample with two Rabbit modules.
* You can define IGMP_VERBOSE in your program, and see what sorts of IGMP-related messages appear on STDOUT (which should identify multicast join/leave).
* Note that sprintf() returns the number of bytes written to the string, and you can use that value instead of immediately calling strlen() on the written string.
answered Mar 2 by TomCollins Veteran of the Digi Community (1,872 points)
...