Example2: tcpecho_server

Description

This example implements a simple TCP echo server.  It listens on Port 7 
for connection requests.  After a client connects, it will echo back 
each message that it receives. This code was intended as a simple 
example of a TCP server program. In order to keep the code simple, it 
will handle only one connection at a time. It will only return the first 
255 bytes of any requests that are longer than 255 bytes. 

You can connect to the example echo server with another embTCP system 
running the TCP echo client of Example1, or you may use any other TCP 
echo client. 

While most Windows and Linux system have TCP echo server, most do not 
have a TCP echo client configured by default.  If they have a Telnet 
client, then you can use Telnet to connect to Port 7 at the IP address 
of the echo server.  Once the connection is made, the echo server will 
echo back anything that you type into the Telnet session.

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.

Code Walkthrough

In tcpecho_server.c, after a few definitions and prototypes, the next 
section defines the TCP task info structure and calls TK_CREATE to 
create the TCP echo server task.  

The function  example_init() creates tcp echo server task. 
Task body tk_ts_echo waits until the network is ready and 
then calls tcp_secho_init.  Tcp_secho_init() calls the main loop of the 
echo server. Tcp_secho_init() only returns if there is an error setting 
up the listening socket. If it does return, the task will be deleted.  

The tcp_secho_init() routine does the following:
* Sets up a socket address structure for listening on port 7 for a 
  connection request from any IP4 address. 
* Calls t_socket(), t_bind() and t_listen so that it can begin listening 
  for connection requests.
* Uses t_setsocketopt to put the socket in non-blocking mode.  This is 
  important because the echo server uses two sockets: one for listening 
  for connection requests and another that is created to listen for 
  incoming messages from an accepted connection. If the listening socket 
  were to block waiting for another connection request, the echo server 
  would not be able to service the requests for the connected socket.
* Allocates a read buffer and calls tcp_echo_recv();

The tcp_echo_recv() routine does the following:
* Goes into a loop.  The "while (1)" expression means it will only exit 
  when "return" is called. 
* Calls t_accept() to check for and accept any received connection request. 
  If the return is a valid socket and we are not already servicing a 
  different connection (This echo server handles only one connection at a 
  time), then we set the global esvr_sock to this newly accepted socket.
* Call t_recv to read any messages received on esvr_sock. A return of 0 
  means the peer closed the socket. A zero return causes us to close 
  esvr_sock, but to continue listening for new connections on elisten_sock.
* If len > 0, we call tesvrecho() to echo back the received data.
* Sleeps for 2 ticks before going back around the loop.

The tesvrecho() routine does the following:
* Calls t_send() and, if necessary, loops until all of the data is sent.  
  The loop is necessary because if the system is congested, the first call 
  to t_send() may return EWOULDBLOCK or it may send only part of the data.  
* If only part of the data was sent, we advance the buffer pointer, 
  subtract bytessent from bytestosend, and yield the system briefly before 
  trying again.

