Hi guys.
I would like to ask several questions about this. Im on my final phase of the proj, will appreciate some information.
Qn 1: How do i make the user continually input till he types 'exit' to exit?
Qn 2: If he types wrongly, or database couldnt find the result, should prompt for try again
Qn 3: How do i make the server accept multiple client connections? Meaning each client is able to display country data independently?
Would appreciate your answers. Heres my code
main prog
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "CountryData.h"
#include <sys/un.h> /* for sockaddr_un struct */
#define DEFAULT_PROTOCOL 0
/* POSIX renames "Unix domain" as "local IPC."
Not all systems define AF_LOCAL and PF_LOCAL (yet). */
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
/****************************************************************/
main ()
{
int serverFd, clientFd, serverLen, clientLen;
struct sockaddr_un serverAddress;/* Server address */
struct sockaddr_un clientAddress; /* Client address */
struct sockaddr* serverSockAddrPtr; /* Ptr to server address */
struct sockaddr* clientSockAddrPtr; /* Ptr to client address */
/* Ignore death-of-child signals to prevent zombies */
signal (SIGCHLD, SIG_IGN);
serverSockAddrPtr = (struct sockaddr*) &serverAddress;
serverLen = sizeof (serverAddress);
clientSockAddrPtr = (struct sockaddr*) &clientAddress;
clientLen = sizeof (clientAddress);
/* Create a socket, bidirectional, default protocol */
serverFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
serverAddress.sun_family = AF_LOCAL; /* Set domain type */
strcpy (serverAddress.sun_path, "recipe"); /* Set name */
unlink ("recipe"); /* Remove file if it already exists */
bind (serverFd, serverSockAddrPtr, serverLen); /* Create file */
listen (serverFd, 5); /* Maximum pending connection length */
char country1[256];
char Capital[256];
char Currency[100];
int n;
while (1) /* Loop forever */
{
/* Accept a client connection */
clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);
if (fork () == 0) /* Create child to send recipe */
{
if (clientFd < 0)
error("ERROR on accept");
readData();
bzero(country1,256);
n = read(clientFd,country1,255);
if (n < 0) error("ERROR reading from socket");
printf("You have entered %s\n", country1);
printf ("%s Capital : %s\n", country1, getCapital (country1));
printf ("%s Currency Code : %s\n", country1, getCurrencyCode (country1));
char* Capital = getCapital (country1);
char* Currency = getCurrencyCode(country1);
n = write(clientFd,"Do you wish to try again?",255);
if (n < 0) error("ERROR writing to socket");
return 0;
close (clientFd); /* Close the socket */
exit (/* EXIT_SUCCESS */ 0); /* Done */
}
else
close (clientFd); /* Close the client descriptor */
}
}
/****************************************************************/
void readData ()
{
FILE * pFile;
NoOfRecordsRead = 0;
char buffer [Line_Char_Buffer_Size];
pFile = fopen (INPUT_FILE_NAME , "r");
if (pFile == NULL)
perror ("Error opening file 'Countries.txt' !");
else
{
while ( fgets(buffer, Line_Char_Buffer_Size,pFile) != NULL)
{
// printf ("%d] aLine => %s\n", NoOfRecordsRead, buffer);
globalCountryDataArray [NoOfRecordsRead++] = createCountryRecord(buffer);
}
fclose (pFile);
}
}
/******************************************************************************************************************/
CountryRecordType createCountryRecord (char* buffer)
{
CountryRecordType ctryRec;
char* pch = strtok (buffer, LINE_DATA_DELIMITER);
// 1) Retrieve TLD
strcpy (ctryRec.TLD, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 2) Retrieve Country
strcpy (ctryRec.Country, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 3) Retrieve FIPS104
strcpy (ctryRec.FIPS104, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 4) Retrieve ISO2
strcpy (ctryRec.ISO2, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 5) Retrieve ISO3
strcpy (ctryRec.ISO3, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 6) Retrieve ISONo
ctryRec.ISONo = atof (pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 7) Retrieve Capital
strcpy (ctryRec.Capital, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 8) Retrieve Region
strcpy (ctryRec.Region, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 9) Retrieve Currency
strcpy (ctryRec.Currency, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 10) Retrieve CurrencyCode
strcpy (ctryRec.CurrencyCode, pch);
pch = strtok (NULL, LINE_DATA_DELIMITER);
// 11) Retrieve Population
ctryRec.Population = atof (pch);
return (ctryRec);
}
/****************************************************************************************************************/
void displayRecordContent (CountryRecordType ctryRec)
{
printf ("TLD : %s\n", ctryRec.TLD);
printf ("Country : %s\n", ctryRec.Country);
printf ("FIPS104 : %s\n", ctryRec.FIPS104);
printf ("ISO2 : %s\n", ctryRec.ISO2);
printf ("ISO3 : %s\n", ctryRec.ISO3);
printf ("ISONo : %lf\n", ctryRec.ISONo);
printf ("Capital : %s\n", ctryRec.Capital);
printf ("Region : %s\n", ctryRec.Region);
printf ("Currency : %s\n", ctryRec.Currency);
printf ("CurrencyCode : %s\n", ctryRec.CurrencyCode);
printf ("Population : %lf\n\n", ctryRec.Population);
}
int findCountryRecord (const char* countryName)
{
int idx = -1;
int found = 0;
while (!found && (++idx < Max_Record_Size))
if (strcmp (globalCountryDataArray [idx].Country, countryName) == 0)
found = 1;
if (found)
return (idx);
else
return (-1);
}
// ====================================================================
char* getCapital (const char* countryName)
{
int idx = findCountryRecord (countryName);
if (idx < 0)
{
printf ("Error! Country '%s' not found\n", countryName);
return (NULL);
}
else
return (globalCountryDataArray [idx].Capital);
}
// ====================================================================
char* getCurrencyCode (const char* countryName)
{
int idx = findCountryRecord (countryName);
if (idx < 0)
{
printf ("Error Country '%s' not found\n", countryName);
return (NULL);
}
else
return (globalCountryDataArray [idx].CurrencyCode);
}
client
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> /* for sockaddr_un struct*/
#define DEFAULT_PROTOCOL 0
/* POSIX renames "Unix domain" as "local IPC."
Not all systems define AF_LOCAL and PF_LOCAL (yet). */
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
/****************************************************************/
main ()
{
int clientFd, serverLen, result;
struct sockaddr_un serverAddress;
struct sockaddr* serverSockAddrPtr;
serverSockAddrPtr = (struct sockaddr*) &serverAddress;
serverLen = sizeof (serverAddress);
/* Create a socket, bidirectional, default protocol */
clientFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
serverAddress.sun_family = AF_LOCAL; /* Server domain */
strcpy (serverAddress.sun_path, "recipe"); /* Server name */
char country1[256];
int n;
do /* Loop until a connection is made with the server */
{
result = connect (clientFd, serverSockAddrPtr, serverLen);
if (result == -1) sleep (1); /* Wait and then try again */
}
while (result == -1);
printf("Please enter country name: ");
scanf("%s",country1);
n = write(clientFd,country1,strlen(country1));
if (n < 0)
error("ERROR writing to socket");
bzero(country1,256);
n = read(clientFd,country1,256);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",country1);
return 0;
/* Send the recipe */
if (country1 == "1"){ close (clientFd); /* Close the socket */
exit (/* EXIT_SUCCESS */ 0); }/* Terminate */
}
/**************************************************************/
Additional Lib
#ifndef COUNTRY_DATA_H
#define COUNTRY_DATA_H
// ====================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// ====================================================================
#define TLD_LEN 2
#define COUNTRY_LEN 100
#define FIPS104_LEN 2
#define ISO2_LEN 2
#define ISO3_LEN 3
#define CAPITAL_LEN 100
#define REGION_LEN 100
#define CURRENCY_LEN 50
#define CURRENCY_CODE_LEN 3
#define No_Of_Rec_Fields 11
#define Max_Record_Size 2500
#define Line_Char_Buffer_Size 4000
#define LINE_DATA_DELIMITER ","
#define INPUT_FILE_NAME "Countries.txt"
// ====================================================================
//const char* LINE_DATA_DELIMITER = ",";
//const char* INPUT_FILE_NAME = "Countries.txt";
typedef struct CountryRecord
{
char TLD [TLD_LEN+1]; // Top Level Domain code
char Country [COUNTRY_LEN+1];
char FIPS104 [FIPS104_LEN+1]; // Ctry code according to FIPS104 standard
char ISO2 [ISO2_LEN+1]; // Ctry code according to ISO2 standard
char ISO3 [ISO3_LEN+1]; // Ctry code according to ISO3 standard
double ISONo;
char Capital [CAPITAL_LEN+1];
char Region [REGION_LEN+1]; // E.g. Asia, Europe, etc.
char Currency [CURRENCY_LEN+1]; // Full name of currency
char CurrencyCode [CURRENCY_CODE_LEN+1]; // Currency abbreviation
double Population;
} CountryRecordType;
int NoOfRecordsRead;
CountryRecordType globalCountryDataArray [Max_Record_Size];
// ====================================================================
void readData ();
char* get_line (char *s, size_t n, FILE *f);
CountryRecordType createCountryRecord (char* aLine);
void displayRecordContent (CountryRecordType ctryRec);
void showAllRecords ();
int findCountryRecord (const char* countryName);
char* getCapital (const char* countryName);
char* getCurrencyCode (const char* countryName);
// ====================================================================
#endif // COUNTRY_DATA_H
finally Countries.txt
SZ,Swaziland,WZ,SZ,SWZ,748.00,Mbabane,Africa,Lilangeni,SZL,1104343.00
TC,Turks and Caicos Islands,TK,TC,TCA,796.00,Cockburn Town,Central America and the Caribbean,US Dollar,USD,18122.00
TD,Chad,CD,TD,TCD,148.00,N'Djamena,Africa,CFA Franc BEAC,XAF,8707078.00
TF,French Southern and Antarctic Lands,FS,TF,ATF,260.00,--,Antarctic Region,Euro,EUR,0.00
TG,Togo,TO,TG,TGO,768.00,Lome,Africa,CFA Franc BCEAO,XOF,5153088.00
TH,Thailand,TH,TH,THA,764.00,Bangkok,Southeast Asia,Baht,THB,61797751.00
TJ,Tajikistan,TI,TJ,TJK,762.00,Dushanbe,Commonwealth of Independent States,Somoni,TJS,6578681.00
TK,Tokelau,TL,TK,TKL,772.00,--,Oceania,New Zealand Dollar,NZD,1445.00
TM,Turkmenistan,TX,TM,TKM,795.00,Ashgabat,Commonwealth of Independent States,Manat,TMM,4603244.00
TN,Tunisia,TS,TN,TUN,788.00,Tunis,Africa,Tunisian Dinar,TND,9705102.00
TO,Tonga,TN,TO,TON,776.00,Nuku'alofa,Oceania,Pa'anga,TOP,104227.00
TP,East Timor,TT,TL,TLS,626.00,--, ,Timor Escudo,TPE,
TR,Turkey,TU,TR,TUR,792.00,Ankara,Middle East,Turkish Lira,TRL,66493970.00
TT,Trinidad and Tobago,TD,TT,TTO,780.00,Port-of-Spain,Central America and the Caribbean,Trinidad and Tobago Dollar,TTD,1169682.00