Concurrent Server

Data Structures

struct  _PARALLEL_SERVER
 Parallel Server structure definition. More...
 

Functions

_PARALLEL_SERVER * add_pserver (uint16_t proto, _PARALLEL_SERVER **pserver_head)
 Add a new concurrent server to the double linked list. More...
 
_PARALLEL_SERVER * get_current_pserver (SOCKET *so, _PARALLEL_SERVER **pserver_head)
 Search pserver list for current socket. More...
 
_PARALLEL_SERVER * get_next_pserver (_PARALLEL_SERVER *pserver, _PARALLEL_SERVER **pserver_head)
 Return the next connected client connection for processing. More...
 
_PARALLEL_SERVER * close_pserver (_PARALLEL_SERVER *pserver, _PARALLEL_SERVER **pserver_head)
 Erase a node from a concurrent server list. More...
 

Detailed Description

This module provides easy to use support for parallel servers ( concurrent server).

Problem: After connecting a listening socket, this socket cannot be reached from any other client until it is disconnected:

Server before connecting:

      192.168.168.100
   -------------------------
  |                          |
  |       *==========*       |
  |       *  Server  *       |
  |       *==========*       |
  |  {192.168.168.100 : 21}  |---> listening socket
  |  { * . * . * . *  : * }  |---> accept all clients
  |                          |
   -------------------------

Server after connecting:

      192.168.168.100
   --------------------------                  --------------------------
  |                          |                |                          |
  |       *==========*       |                |       *==========*       |
  |       *  Server  *       |   connected    |       *  Client  *       |
  |       *==========*       |<-------------->|       *==========*       |
  |  {192.168.168.100 : 21}  |                |  {192.168.168.200 :1550} |
  |  {192.168.168.200 :1550} |                |  {192.168.168.100 : 21}  |
  |                          |                |                          |
   --------------------------                  --------------------------

Operating systems like Linux use fork() or something similar to create a runtime copy of the listening server. A new connection query results in one connected and one listening server.

Server after connecting:

      192.168.168.100
   --------------------------                  --------------------------
  |                          |                |                          |
  |       *==========*       |                |       *==========*       |
  |       *  Server  *       |   connected    |       *  Client  *       |
  |       *==========*       |<-------------->|       *==========*       |
  |  {192.168.168.100 : 21}  |                |  {192.168.168.200 :1550} |
  |  {192.168.168.200 :1550} |                |  {192.168.168.100 : 21}  |
  |                          |                |                          |
  |                          |                 --------------------------
  |       *==========*       |
  |       *  Server  *       |   listening
  |       *==========*       |<--------------
  |  {192.168.168.100 : 21}  |
  |  { * . * . * . *  : * }  |
  |                          |
   --------------------------

The next connection query from the next client (or even the same client with a different source port) results in two connected sockets and again one listening socket:

      192.168.168.100
   --------------------------                  --------------------------
  |                          |                |                          |
  |       *==========*       |                |       *==========*       |
  |       *  Server  *       |   connected    |       *  Client  *       |
  |       *==========*       |<-------------->|       *==========*       |
  |  {192.168.168.100 : 21}  |                |  {192.168.168.200 :1550} |
  |  {192.168.168.200 :1550} |                |  {192.168.168.100 : 21}  |
  |                          |                |                          |
  |                          |                 --------------------------
  |                          |                 --------------------------
  |                          |                |                          |
  |       *==========*       |                |       *==========*       |
  |       *  Server  *       |   connected    |       *  Client  *       |
  |       *==========*       |<-------------->|       *==========*       |
  |  {192.168.168.100 : 21}  |                |  {192.168.168.201 :2345} |
  |  {192.168.168.201 :2345} |                |  {192.168.168.100 : 21}  |
  |                          |                |                          |
  |                          |                 --------------------------
  |                          |
  |                          |
  |       *==========*       |
  |       *  Server  *       |   listening
  |       *==========*       |<--------------
  |  {192.168.168.100 : 21}  |
  |  { * . * . * . *  : * }  |
  |                          |
   --------------------------

With this procedure always one socket is listening on the dedicated port until the maximum amount of parallel connections is reached.

Without Operating System ( or without the option to use a runtime copy of code by calling fork()) the user has two possible ways to handle concurrent servers.

The static list occupies more data memory and is more inflexible, on the other hand the dynamic list needs more code for administration.

This module implements the dynamic version of parallel servers. Refer to the PServer.c example in your D.SignT\Network\DM2DM642EMAC\Projects directory for more details.

Function Documentation

_PARALLEL_SERVER* add_pserver ( uint16_t  proto,
_PARALLEL_SERVER **  pserver_head 
)

This function adds a new listening server socket to the parallel server list. It must be called at least once for initialization and to have one socket listening. Any time a new connection from a client is established (SO_CONNECTION_ESTABLISHED in socket_struct::error_code) this function must be called to add a new listening socket and to maintain the socket list.

Parameters
proto- IP-port for specific protocol
**pserver_head- user defined head of server list
Returns
  • Pointer to a new parallel server structure
  • or NULL - out of memory
Library:
net.lib
Prototype:
pserver.h
Examples:
PServer.c.
_PARALLEL_SERVER* get_current_pserver ( SOCKET *  so,
_PARALLEL_SERVER **  pserver_head 
)

This function returns a pointer to the server connection the socket 'so' belongs to. It is useful in callback functions to get more information about the current connection.

Note
Useful in callback function
Parameters
*so- connected socket
**pserver_head- user defined list head
Returns
Pointer to the next list entry
Library:
net.lib
Prototype:
pserver.h
Examples:
PServer.c.
_PARALLEL_SERVER* get_next_pserver ( _PARALLEL_SERVER *  pserver,
_PARALLEL_SERVER **  pserver_head 
)

For quasi parallel processing all connections must be serviced one at a time. The main server function uses this routine to walk through the list of all connected clients to handle the next connection that is waiting for processing.

Parameters
*pserver- user pointer to server
**pserver_head- user defined list head
Returns
next waiting connection
Library:
net.lib
Prototype:
pserver.h
_PARALLEL_SERVER* close_pserver ( _PARALLEL_SERVER *  pserver,
_PARALLEL_SERVER **  pserver_head 
)

If a connection was closed (or reset), the corresponding node in the list must be deleted. Use this function to close the socket and to free all associated memory.

Parameters
*pserver- server to close
**pserver_head- user defined list head
Returns
always NULL
Library:
net.lib
Prototype:
pserver.h
Examples:
PServer.c.