Example3: udpecho_client.c Description This example implements a simple UDP echo client. It connects to a UDP echo server, periodically sends echo requests and then validates that the data in the received response exactly matches the data sent. If it is linked into the DEBUG version of embTCP and is run on a system with a console, it will print status messages. Otherwise, you will only be able to see what there are doing by looking at a WireShark trace. The initialization routine for all of the embTCP example programs is called example_init. For this reason, you can only link with one example at a time on an embTCP system. When example_init is called, it will create and initialize a task and begin running. Example3 was intended as a simple example of a UDP client program. It is not a robust UDP echo client. It starts immediately once it has been initialized, sends 10 echo requests of 255 bytes each at a fixed rate, listens for responses and then exits by deleting its task. Note: The target UDP echo server needs to be running when udpecho_client is initialized. Once initialized, the udpecho_client immediately attempts to connect. If the server is not running, the connection request will timeout and the task will return to its task loop where it will be deleted. Configuration Parameters You must change the 'svraddrstr' parameter to be the IP address of a UDP echo server. The other parameters should not be changed for the initial tests. Most Windows and Linux systems have a running UDP echo server that will respond to echo requests. You could also send the requests to another system running embTCP with example 4, a UDP echo server. Code Walkthrough The UDPCLIENT structure holds the input and output buffers and the variables that are maintained across all of the echo requests. The next section defines the UDP task info structure and calls TK_CREATE to create the UDP echo client task. The function examle_init() creates udp echo client task. Task body tk_uc_echo waits until the network is ready and then calls udp_ceho_init(). udp_cecho_init() calls the main loop of the echo client. Most tasks run for the life of the system. However, the UDP echo task runs only long enough to send the configured number of echo requests. When it returns to the task loop, the task is deleted. The udp_cecho_init() routine does the following: * Converts the IP address string to a binary number * Sets its own address structure and calls t_bind in order to listen for UDP echo responses addressed to it from any address. It lets the OS pick the local port number. * Fills out the address structure for the remote server. * Opens a socket and calls t_connect(). The connect routine blocks and will not return until either the connection has been made or it times out. Note: If the server is not running, when the t_connect() times out it will print a connection error message and return to the task loop where the task will be deleted. * Calls t_setsockopt() to put the socket in non-blocking mode. * Calls udp_send_an_echo to send the first echo request. * If there is no error, it calls udp_cecho_loop() to send the rest of the requests. * Call udp_cehco_close when udp_cecho_loop returns. * Returns to the main task loop where the task will be deleted. The udp_cecho_loop does the following: * Goes into a loop. The "for(;;)" expression means it will only exit when "return" is called. * Calls t_select() to see if there are any responses ready to be read. It sets the timeout value for t_select to 200 ms. This allows it to test to see if it is time to send another echo request. * Calls t_recv() to read any available echo response. * If the return from t_recv ('len') is < 0 it calls t_errno to determine the error number. If the return is anything other the EWOULDBLOCK, it will print an error message. * If 'len' is greater than 0, then we read an echo response. Note if the system were congested, the full response may not be read in a single t_recv() call. * Loops to validate each byte of the received data. The variable 'uec->nextrcvbyte' hold the value of the next expected byte. When uec->nextrcvbyte increments to ECHODFTLEN, it is reset to 0. If we find an unexpected character, we print and error message and return. * After a successful read, the number of replies is incremented and 'len' is added to the cumulative total number of bytes read. * When the number of requests sent equals the configured number of requests to send, udp echo has completed and will return. * Otherwise, if it is time to send another request, it calls udp_send_an_echo. The udp_send_an_echo() routine does the following: * Fills each byte of the outgoing buffer with values incrementing from 0 to ECHODFTLEN - 1. * The tcp_send_an_echo routine will loop until all bytes in the request are sent. If the system is congested, then t_send may return EWOULDBLOCK or a t_send it may send only part of the data. * If the t_send call blocks, we call taskYIELD() to let other tasks run. On return we continue in the send loop. * If t_send return a positive value, then we add that value to the number of bytes sent. If only part of the data was sent, we advance the buffer pointer and reduce bytestosend by the number of bytes sent. * Once the full echo request has been sent, we increment the statistics variables and set the timer for when the next request should be sent. The udp_cecho_close() routine does the following: * If there is a valid socket, it closes it. * Prints a completion status message.