UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


projects:high_altitude_slug:software:client

Client library

Functions

client_init

The client_init function should be called before any other client related functions and connects to serverAddr (probably localhost) on port port. Both of these values should be #defined in config.h as SERVER and PORT respectively. The function is prototyped as:

int client_init (char *serverAddr, unsigned short port);

in client.h

On success client_init function returns the socket file descriptor of the server that it has connected to which should be passed to all client-related functions. On failure the function returns -1 and makes a note in the client error log.

client_recv_packet

The client_recv_packet function is used to read packets of data from the server. It reads a single packet of data from serverFD (the servers network file descriptor returned by client_init) and then places the packet into packet which should be a pointer to a client_packet structure. It is prototyped as:

int client_recv_packet (unsigned short serverFD, struct client_packet *packet);

in client.h

The client_recv_packet function will automatically perform byte-conversions on packet→command and packet→len using the ntohs function.

First of all the function will read 4 bytes of data from the serverFD, convert them to the host byte order and then use the packet→len variable to work out the length of the data segment of the packet. Next, malloc is used to allocate enough memory to store the data segment of the packet and the null byte (packet→len + 1), before going onto reading the data segment into the newly allocated string and then setting the last byte to \0.

Please note the the data segment of the packet (packet→data) is made up of memory allocated off of the heap, and so needs to be free()'ed when no longer needed to prevent a memory leak!

On success this function will return 0 while on failure this function will return -1 and will make a note in the error log about exactly what went wrong.

client_recv_packets

The client_recv_packets function is very similar to the client_recv_packet function, except that it will return all of the packets in the buffer and will allocate memory as required. Unlike client_recv_packet the client_recv_packets function is non-blocking and will return if there is nothing in the buffer. It is prototyped as:

struct client_packet *client_recv_packets(unsigned short serverFD, int *npackets);

in client.h

Since this function makes calls to the client_recv_packet function to actually read the data from the buffer it also performs byte-conversions on command and len member variables.

On success this function returns a pointer to a client_packet structure and places the number of items read from the server into npackes. On failure, packet is returned (which is by default initialised to NULL) and npackets is set to 0.

client_send_packet

The client_send_packet function should be used to send a packet of information to the server (aka the 'party line'). It sends packet to serverFD (which is the servers file descriptor) and is prototyped as:

int client_send_packet (unsigned short serverFD, struct client_packet *packet);

in client.h

Like the client_recv_packet function the client_send_packet function will automatically perform byte-conversions on both packet→command and packet→len to convert them to the network byte order using htons function.

On success the function will return 0 otherwise, on failure, will return -1 and make a note in the error log about what went wrong.

client_close

The client_close function simply closes serverFD by calling the close function (which it is no more than a wrapper over) and is prototyped as:

void client_close (unsigned short serverFD)

in client.h

client_close should be called when the connection to the server ('party line') is no longer needed.

Example

Here is a simple application that demonstrates the use of these functions. The program basically forks (creates a copy of) itself. Both of the processes then connect to the server, once a connection has been established the child process will then wait for 0.25 seconds, giving the parent process time to send two packets of data to the party line at which point the parent process then exits. After the child processes 0.25 second wait has elapsed it will call the client_recv_packets function to read all of the packets from the server (which should be the two that the parent sent) and then prints them out to the terminal before free()ing all of the memory allocated by the client_recv_packets function and exiting.

/***************************************************************************
 *   Copyright (C) 2006 the `High Altitude Slug Project'                   *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/
 
/*
 * Slug
 * test_client.c
 * By: Freddie Witherden
 * A simple test application designed to test both the server and client
 * libraries
 */
 
/* Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <stdint.h>
#include <unistd.h>
#include "config.h"
#include "client.h"
 
/* Messages and command words to be sent */
#define CMD_1 100
#define MSG_1 "foo is to bar as spam is to eggs"
 
#define CMD_2 7000
#define MSG_2 "this statement is false!"
 
int main (void)
{
	int serverFD;				/* Server network file descriptor	*/
	pid_t pid;					/* Process ID, for fork				*/
 
	/* Fork */
	if ((pid = fork()) == -1)
	{
		/* Error */
		fputs("Error fork()ing the process\n", stderr);
		exit(EXIT_FAILURE);
	}
	else if (pid == 0)
	{
		/* Child */
		struct client_packet *message;	/* For pointing to the recieved message		*/
		int npackets;					/* For holding the number of packets read	*/
		int i;
 
 
		/* Connect */
		serverFD = client_init(SERVER_HOST, SERVER_PORT);
 
		if (serverFD == -1)
		{
			fputs("Error connecting to the server (are you sure it is running?)\n", stderr);
			exit(EXIT_FAILURE);
		}
 
		/* Sleep for 0.25 secs */
		usleep(250000);
 
		/* Read the data from the server that the parent has sent */
		message = client_recv_packets(serverFD, &npackets);
 
		if (message == NULL)
		{
			fputs("Error reading packets from the server\n", stderr);
			exit(EXIT_FAILURE);
		}
 
		/* Print out the packets */
		for (i = 0; i < npackets; i++)
		{
			printf("Comamnd word is: %i\n", message[i].command);
			printf("Length of data segment is: %i\n", message[i].len);
			printf("Data segment is: \"%s\"\n", message[i].data);
		}
 
		/* Free the allocated memory */
		for (i = 0; i < npackets; i++) free(message[i].data);
 
		free(message);
	}
	else
	{
		/* Parent */
		struct client_packet messages[2] = {
			{ CMD_1, MSG_1, strlen(MSG_1) },
			{ CMD_2, MSG_2, strlen(MSG_2) }
		};
 
		/* Connect */
		serverFD = client_init(SERVER_HOST, SERVER_PORT);
 
		if (serverFD == -1)
		{
			fputs("Error connecting to the server (are you sure it is running?)\n", stderr);
			exit(EXIT_FAILURE);
		}
 
		/* Send the messages */
		if (client_send_packet(serverFD, &messages[0]) == -1
			|| client_send_packet(serverFD, &messages[1]) == -1)
		{
			fputs("Error sending packets to the server\n", stderr);
			exit(EXIT_FAILURE);
		}
	}
 
	/* Close the connection */
	client_close(serverFD);
 
	return 0;
}
projects/high_altitude_slug/software/client.txt · Last modified: 2008/07/19 23:33 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki