Example1: tcpecho_client Description This example implements a simple TCP echo client. It connects to a TCP 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. Example 1 was intended as a simple example of a TCP client program. It is not a robust TCP 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 TCP echo server needs to be running when tcpecho_client is initialized. Once initialized, the tcpecho_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 TCP echo server. The other parameters should not be changed for the initial tests. Most Windows and Linux systems have a running TCP echo server that will respond to echo requests. You could also send the requests to another system running embTCP with example 2, a TCP echo server. Code Walkthrough The TCPCLIENT structure holds the input and output buffers and the variables that are maintained across all of the echo requests. The next section defines the TCP task info structure and calls TK_CREATE to create the TCP echo client task. The function example_init() creates the tcp echo client task. Task body tk_tc_echo waits until the network is ready and then calls tec_init. Tec_init() calls the main loop of the echo client. Most tasks run for the life of the system. However, the TCP 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 tec_init() routine does the following: * Converts the IP address string to a binary number * Allocates a TCPCLIENT structure. * Sets the tec->nextsend to the current time so that an echo request will be sent as soon as we are ready. * 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 tcp_send_an_echo to send the first echo request. * If there is no error, it calls tcecho_loop() to send the rest of the requests. The tcp_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 tcecho_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 and call tcp_client_close. * 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 'tec->nextrcvbyte' hold the value of the next expected byte. When tec->nextrcvbyte increments to ECHODFTLEN, it is reset to 0. If we find an unexpected character, we print and error message and close the connection. * 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, tcp echo has completed. It calls tcp_client_close() to clean up and returns. * Otherwise, if it is time to send another request, it calls tcp_send_an_echo. When the TCP echo client is ready to close for any reason, it calls tcp_client_close() to clean up the connection. The tcp_client_close() routine does the following: * If there is a valid socket, it closes it. * If there is an allocated TCPCLIENT structure, it frees it.