user1679956
user1679956

Reputation:

Trouble reading data from server

I am currently having trouble reading multiple values from a server. This is a client/server program. User is supposed to key in the country name in the client and then server will return the capital of the country and its currency. I successfully keyed in the first input example China, the server returns the correct data. However, when I keyed in subsequent values as Singapore. They returned nothing. Hope you guys can tell me what's wrong with the code. The server is supposed to return the capital and currency of the country that is keyed in.

Below are my codes for the server and client. Sorry, they are a little long but i guess its better that I give you guys the full picture

server.c

#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 */
#include <string.h>
#include "country.h"
#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


/****************************************************************/
 int 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, "country"); /* Set name */

    unlink ("country"); /* Remove file if it already exists */

    bind (serverFd, serverSockAddrPtr, serverLen); /* Create file */ 
    listen (serverFd, 5); /* Maximum pending connection length */


    printf ("%s \n", "Starting Country Server");
    printf ("%s \n", " ");

    while (1) /* Loop forever */
      {
        /* Accept a client connection */
        clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);

        if (fork () == 0) /* Create child to send recipe */
          {
            //writeCountryData (clientFd); /* Send the recipe */
       while(1)
       {
        readCountry (clientFd);
            close (clientFd); /* Close the socket */

            exit (/* EXIT_SUCCESS */ 0); /* Terminate */
          }
        else
          close (clientFd); /* Close the client descriptor */
      }

    return 0;
   }

   /****************************************************************/

 readCountry (int fd)
 {

    readData();
    char capital[100]="", currencyCode[100]="", *p;
        char userInput[200];

        read(fd, userInput, 200);

    if ((p = strchr(userInput, '\n')) != NULL) /* to remove the [enter] from userinput */
        *p = '\0';

    strcat(capital,userInput) ;
    strcat(capital," Capital       : ") ;
    strcat(capital,getCapital (userInput));

    write (fd, capital, strlen (capital) + 1);
    strcat(currencyCode,userInput) ;
    strcat(currencyCode," Currency Code       : ") ;
    strcat(currencyCode,getCurrencyCode (userInput));
    write (fd, currencyCode, strlen (currencyCode) + 1);


 }

readLine (int fd, char* str)
 {
   int n;
   do /* Read characters until NULL or end-of-input */
     {
     // ssize_t read (int fd, void *buf, size_t count);
     // if successful, read will:
     // a) stores data read into 'buf', and
     // b) returns the no. of bytes read
     // read returns zero if it reaches end-of-input
       n = read (fd, str, 1); /* Read one character */
     }
   while (n > 0 && *str++ != 0);
   return (n > 0); /* Return false if end-of-input */
 }





}

client.c

#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, "country"); /* Server name */
   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);

    while (1)
    {
    char country[300];
    printf("To end program, type 'end' \n");
    printf("Please enter country name >");
    fgets(country,sizeof(country),stdin);
    if (strcmp(country,"end\n") == 0)
    {
        printf("Thank you for using country services\n");
        break;

    }
    else 
    write(clientFd,country,strlen(country));
    readCountry(clientFd);
    close(clientFd);


    }


    /* Read the recipe */

    /* Close the socket */
   exit (/* EXIT_SUCCESS */ 0); /* Done */




 }
 /**************************************************************/

 readCountry(int fd)
 {
   char str[300];

   while (readLine (fd, str)) /* Read lines until end-of-input */
     printf ("%s\n", str); /* Echo line from socket */
 }

 /**************************************************************/

 /* Read a single NULL-terminated line */
 readLine (int fd, char* str)
 {
   int n;
   do /* Read characters until NULL or end-of-input */
     {
     // ssize_t read (int fd, void *buf, size_t count);
     // if successful, read will:
     // a) stores data read into 'buf', and
     // b) returns the no. of bytes read
     // read returns zero if it reaches end-of-input
       n = read (fd, str, 1); /* Read one character */
     }
   while (n > 0 && *str++ != 0);
   return (n > 0); /* Return false if end-of-input */
 }

  writeUserInput(int fd)
  {

   char text[20];
   printf("To end program, type 'end' \n\n\n");
   printf("Please enter Country > ");
   fgets (text, sizeof(text), stdin);



   write (fd, text, strlen (text) + 1);

  }

Upvotes: 2

Views: 391

Answers (1)

NullPoiиteя
NullPoiиteя

Reputation: 57312

Server Comments You need to set the socket size each time.

 /* Accept a client connection */
   clientLen = sizeof (clientAddress);    // this line was missing
   lientFd = accept (serverFd, clientSockAddrPtr, &clientLen);

In fact, if you declare variables where they're used, then RAII removes this class of problem.

I've just noticed this is C and not C++, so forget the RAII comment, but the size does need to be set.

You should be using sizeof in:

  char userInput[200];

  read(fd, userInput, 200);

And strncat should be used in:

 char capital[100]="", currencyCode[100]="", *p;
    //...
strcat(capital,userInput) ;
strcat(capital," Capital       : ") ;

and the same for currencyCode.

You don't actually need the fork(), it can all be done in one thread/process.

Client Comments

The code is:

  connect to server

  while (true)
   get input
   send request
   read reply
   close connection to server

Upvotes: 3

Related Questions