Networking

Relevant Files:

Architecture:

This year’s system is a TCP/IP-based server-client architecture based on Winsock (the standard Window’s network library). In our setup, nodes have three possible designations: JUST_SEND, JUST_RECEIVE, and SEND_RECEIVE. JUST_SEND is used for server nodes, JUST_RECEIVE, for clients, and SEND_RECIEVE designates a node which can act as both.

Server Side:

To instantiate a server, one must specify the type, the address, and port number the server is to be established with. Once instantiated, the server sets up a listening socket on the specified port and creates a data structure for managing connections. The server then starts a listener running on a separate thread so it is free to perform other tasks while also monitoring any connection requests. When a client requests a connection from the server, a handshake is initiated (standard TCP/IP) to confirm the connection.

Client Side:

In order to establish a connection with the server, the client is first instantiated using the appropriate IP address and port number and the connection() method is called. The client type and server type must match for a connection to open successfully. For example if the server type and/or client type is not recognized or not an allowable configuration (senseless to have two JUST_SEND entities connect to each other), the connection will not be created. If the connection succeeds, the client and server can communicate using the send() and receive() methods.

Connection-oriented (TCP) Network Applications:

Server
Client

Details:

CommType is a structure that defines the communication mode the client or server can take on. These modes include: duplex mode defined as SEND_RECEIVE, send-only mode defined as JUST_SEND, and receive-only mode defined as JUST_RECEIVE.

Class Socket: Contains methods to set up a socket connection; open/close connection; send and receive data over the connection. It is uses the Winsock library and provides the basic calls which are used by both client and server classes. In order to use this class, user should use ws2_32.lib when linking. This can be done by going to Project->Settings in Visual C++. Click on the Link tab and within Object/library modules, add the statement: “ws2_32.lib”

Method Details:

Socket()
Default constructor. Creates a new Socket object

bool openConnection( char* hostname, int port )
The method opens a connection when given a hostname and port number.

Input parameters:
hostname: The hostname of the server
port: port number of the server

Return value:
returns 1 if successful, 0 if failed

bool openListener( char* hostname, int port )
This method opens a listening socket using the given hostname and port number; it then binds the new socket and starts listening for an incoming connection. Listeners are used to listen for incoming connection requests.

Input parameters:
hostname: The hostname of the server
port: port number of the server

Return value:
returns true if successful, false if failed

bool isOpen()
This method checks if a connection is currently open

Return value:
Return true if connected, false if not connected

void close()
This method closes a connection

bool sendData( char* message, int size )
This method sends data over a socket connection. It returns true if successful and returns false if:
1) the size of data sent is not the same as the size of actual data
2) the connection is already closed

Input parameter:
message: pointer to the message that would like to send
size: size of the message

Return value:
Return true if successful, false if failed

bool receiveData( char* message, int size )
This method is used to receive data over a socket connection. It returns true if the data is received correctly, and false if:
1) the size of data received is not the same as the size of actual data
2) the connection is already closed

Input parameter:
message: pointer to buffer to the message that would like to receive
size: size of the message

Return value:
Return true if success, false if fail

Socket* acceptConnection()
This method accepts an incoming connection request

Return value:
Return a newly connected socket

Class Server: This class includes everything needed to create and use a Server. Methods include setting up a connection; listening and accepting incoming socket connections; sending and receiving data from different client types. The methods are built from calls to the socket class.

Method Details:

Server (CommType serverType, int MaxSend, int MaxReceive )
Constructor of the server class. It takes in the type of server. Possible types are defined in CommType.h and are as follows:
JUST_SEND: server that only sends data (e.g. Vision)
JUST_RECEIVE: server that only receives data
SEND_RECEIVE: server that both sends and receives data

Servers accept a certain max number of clients that can send and/or receive data

Input parameter:
serverType: Type of the server
MaxSend: store the max number of clients of type JUST_RECEIVE and SEND_RECEIVE
MaxReceive: store the max number of clients of type JUST_SEND and SEND_RECEIVE

bool startListener( char* hostname, int port )
This method generates a thread to listen for connection requests. A connection will be accepted if given the client satisfies both of the following conditions:
1) The server and client types are compatible
2) There are still available slots for the incoming client type.
It also checks if there is already a connection set up for the client. If there is, the server ignores the new connection request and returns false.

Input parameter:
Hostname: hostname of the server would like to connect to
Post: port number of the server client would like to connect to

Return value:
Return true if successful, false if failed

void listen()
This method is called by startListener() and it accepts connections from the listener socket and assigns them to the proper client index by calling the appropriate private methods –addSender();
addReceiver() and addSenderReceiver():

1) For JUST_SEND client type, calls addSender()
2) For JUST_RECEIVE client type, calls addReceiver()
3) For SEND_RECEIVE client type, calls addSenderReceiver()

void sendAll( void* message, int size )
This method sends data to all receiving clients, which includes JUST_RECEIVE and SEND_RECEIVE

Input parameter:
message: pointer to buffer to the message that would like to receive
size: size of the message

bool send(int clientIndex, void* message, int size)
This method sends data to a particular client who has the given clientIndex value

Input parameter:
clientIndex: use to identity the client. It is the index of the private variable - sendIndex[] array
message: pointer to buffer to the message that would like to send
size: size of the message
Return value:
Return true if success, false if failed

bool receive(int clientIndex,void* message,int size)
This method receives data from a particular client who has the given clientIndex value

Input parameter:
clientIndex: use to identity the client. It is the index of the private variable - receiveIndex[] array
message: pointer to buffer to the message that would like to receive
size: size of the message

Return value:
Return true if successful, false if failed

void setSendBuffer(int bufSize)
This method set the size of the sender’s buffer. The buffer size for RoboCup is not much of an issue since the typical amount of data which is sent in a packet is small, and considerably smaller than the default kernel buffer size of 8192.

Input parameter:
bufSize: size of the buffer

void setReceiveBuffer(int bufSize)
This method set the size of the receiver’s buffer
Input parameter:
bufSize: size of the buffer

Class Client: This class includes everything needed to create and use a Client. Methods include setting up a connection; checking connection status; sending and receiving data. The methods are built from calls to the socket class.

Method details:
Client(CommType clientType)
The client constructor uses a default host address of 127.0.0.1 (loopback/localhost address) and port number 4545.

Input parameters:
clientType: defines the client’s communication mode by either SEND_RECEIVE, JUST_SEND or JUST_RECEIVE.

Client(CommType clientType, const char* hostname, int port)
This is a constructor to create Client with user-specified communication type and user-defined server address and port number.

Input parameter:
clientType: defines the client’s communication mode by SEND_RECEIVE, JUST_SEND and JUST_RECEIVE
hostname: defines the address to connect to
port: defines the port number to connect to

bool openConnection()
This method opens a connection to communicate with the server having address defined as “Client->hostname” and port number as “Client->port”.

Return Value:
Returns true if connection is opened successfully and false if the client type is rejected by the server or connection fails.

bool openConnection( const char* hostname, int port )
This method opens a connection to communicate with the specified server.
Input parameter:
hostname: defines the server’s address
port: defines the server’s port number
Return Value:
Returns true if successful and false if open connection fails.

bool isOpen()
This method checks if the client has opened a connection with a server.

Return Value:
Returns true if successful and false if open connection fails.

void close()
This method closes a client connection.
Input parameter: None
Return Value: None

bool send( void* message, int size )
This method sends a message of the specified size to the server. It also performs a check to ensure server is not in JUST_SEND mode.

Input parameter:
message: pointer to the message to be sent
size: length of the message
Return Value:
Return true if data is sent and false if the server is defined to be in the send-only mode.

bool receive( void* message, int size )
This method receives a message of the specified size from the server. It also performs a check to ensure the server is not in the JUST_RECEIVE mode.
Input parameter:
message: pointer to the message to be received.
size: length of the message
Return Value:
Return true if data is received and false if the server is defined to be in the JUST_RECEIVE mode.

Constraints:

Networking is one of many pieces whose combined time must be under 16.6ms so that our system is able to run at 60 frames per second. Because our system is currently running on a 100Mb/s local Ethernet there negligible timing delays once our packets get to the wire. It is important to have the Nagle algorithm switched off, since the Nagle algorithm clusters packets and prevents them from being sent immediately (it does so as to avoid the “silly window” syndrome which is more of a problem for networks with higher overall utilization). Due to the real-time qualities of our domain, it is critical that we send packets as soon as possible, thus the Nagle algorithm should stay off.