c - 从服务器读取数据时出现问题

标签 c sockets

我目前无法从服务器读取多个值。 这是一个客户端/服务器程序。 用户需要在客户端输入国家名称,然后服务器将返回该国家的首都及其货币。 我成功地键入了第一个输入示例中国,服务器返回了正确的数据。然而,当我输入后续值“新加坡”时。他们什么也没返回。希望大家能告诉我代码有什么问题。服务器应该返回键入的国家的资本和货币。

下面是我的服务器和客户端代码。抱歉,它们有点长,但我想最好给你们提供完整的图片

服务器.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 */
 }





}

客户端.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);

  }

最佳答案

服务器评论 每次都需要设置套接字大小。

 /* 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(),它可以在一个线程/进程中完成。

Client Comments

代码是:

  connect to server

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

关于c - 从服务器读取数据时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12475531/

相关文章:

C:如何将结构添加到指针数组

c - 使用strtok解析C中的字符串并存储在数组中

c++ - 重载 malloc 以跟踪第三方库的内存使用情况

当服务器被杀死时,Ruby TCPSocket 不会注意到它

c - rand() 在 OSX 上是否返回零?

c - Socket 客户端发送 1 个长字符串而不是 3 个字符串

c# & java 套接字和字节数据读取开销

c - 套接字在recv之前关闭而不调用close

java - 带Executor和不带Executor的多线程区别

c - 定时器和信号中的问题