2

現在、サーバーから複数の値を読み取るのに問題があります。これはクライアント/サーバープログラムです。ユーザーはクライアントに国名を入力することになっています。その後、サーバーは国の首都とその通貨を返します。最初の入力例である中国のキー入力に成功しました。サーバーは正しいデータを返します。しかし、その後の値をシンガポールとして入力したとき。彼らは何も返しませんでした。コードの何が問題になっているのか教えていただければ幸いです。サーバーは、入力された国の資本と通貨を返すことになっています。

以下は、サーバーとクライアントの私のコードです。申し訳ありませんが、少し長いですが、全体像をお伝えしたほうがいいと思います

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);

  }
4

1 に答える 1

3

サーバーコメント毎回ソケットサイズを設定する必要があります。

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

実際、変数が使用されている場所で変数を宣言すると、RAIIはこのクラスの問題を取り除きます。

これはC++ではなくCであることに気付いたので、RAIIコメントを忘れてください。ただし、サイズを設定する必要があります。

sizeofを使用する必要があります:

  char userInput[200];

  read(fd, userInput, 200);

また、strncatは次の場所で使用する必要があります。

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

通貨コードについても同じです。

実際にはfork()は必要ありません。すべて、1つのスレッド/プロセスで実行できます。

Client Comments

コードは次のとおりです。

  connect to server

  while (true)
   get input
   send request
   read reply
   close connection to server
于 2012-09-18T10:55:32.883 に答える