Unix клиент и сервер застряли в бесконечном цикле после чтения файла клиенту - PullRequest
0 голосов
/ 08 сентября 2011

В настоящее время я делаю простой клиент и сервер, но столкнулся с проблемой. Часть системы предназначена для того, чтобы клиент запрашивал локальный файл на сервере. Содержимое этого файла должно быть затем отправлено клиенту. Я могу отправить весь текст в файл клиенту, однако он застрял в цикле чтения на клиенте. Ниже приведены примеры кода для клиента и сервера, предназначенные для решения этой проблемы:

Код клиента, который читает цикл

 else if(strcmp(commandCopy, get) == 0)
        {

            char *ptr;
            int total = 0;
            char *arguments[1024];
            char copy[2000];
            char * temp;
            int rc;

            strcpy(copy, command);

            ptr = strtok(copy," ");

            while (ptr != NULL)
            {
                temp = (char *)malloc(sizeof(ptr));
                temp = ptr;
                arguments[total] = temp;
                total++;
                ptr = strtok (NULL, " ");
            }

            if(total == 4)
            {
                if (strcmp(arguments[2], "-f") == 0)
                {
                    printf("1111111111111");
                    send(sockfd, command, sizeof(command), 0 );
                    printf("sent %s\n", command);
                    memset(&command, '\0', sizeof(command));

                    cc = recv(sockfd, command, 2000, 0);
                    if (cc == 0)
                    {
                        exit(0);
                    }

                }
                else
                {
                    printf("Here");
                    strcpy(command, "a");
                    send(sockfd, command, sizeof(command), 0 );
                    printf("sent %s\n", command);
                    memset(&command, '\0', sizeof(command));

                    cc = recv(sockfd, command, 2000, 0);
                }
            }
            else
            {
                send(sockfd, command, sizeof(command), 0 );
                printf("sent %s\n", command);
                memset(&command, '\0', sizeof(command));

                while ((rc = read(sockfd, command, 1000)) > 0) 
                {
                    printf("%s", command);
                }

                if (rc)
                    perror("read");
            }



        }

Код сервера, который читает файл

char* getRequest(char buf[], int fd)
{

    char * ptr;
    char results[1000];
    int total = 0;
    char *arguments[1024]; 
    char data[100];

    FILE * pFile;
    pFile = fopen("test.txt", "r");

    ptr = strtok(buf," ");

    while (ptr != NULL)
    {
        char * temp; 
        temp = (char *)malloc(sizeof(ptr));
        temp = ptr;
        arguments[total] = temp;
        total++;
        ptr = strtok (NULL, " ");
    }

    if(total < 2)
    {
        strcpy(results, "Invaild Arguments \n");
        return results;
    }

    if(pFile != NULL)
    {
        while(fgets(results, sizeof(results), pFile) != NULL)
        {
            //fputs(mystring, fd);
            write(fd,results,strlen(results));
        }
    }
    else
    {
        printf("Invalid File or Address \n");
    }
    fclose(pFile);
    return "End of File \0";
}

Код сервера для выполнения команды

else if(strcmp(command, "get") == 0)
{
    int pid = fork();
    if (pid ==-1) 
    {
        printf("Failed To Fork...\n");
        return-1;
    }
    if (pid !=0)
    {
       wait(NULL);

    }
    else
    {

       char* temp;
       temp = getRequest(buf, newsockfd);

       strcpy(buf, temp);

       send(newsockfd, buf, sizeof(buf), 0 );
       exit(1);
    }

}

Ответы [ 2 ]

1 голос
/ 12 октября 2011

Целое предложение else if в клиентском коде немного велико для функции, не говоря уже о части функции, какой она предположительно является. Логика в коде ... интересна. Разберем первый раздел:

else if (strcmp(commandCopy, get) == 0)
{
    char *ptr;
    int total = 0;
    char *arguments[1024];
    char *temp;

    ptr = strtok(copy, " ");

    while (ptr != NULL)
    {
        temp = (char *)malloc(sizeof(ptr));
        temp = ptr;
        arguments[total] = temp;
        total++;
        ptr = strtok(NULL, " ");
    }

Я удалил нематериальные объявления и некоторый код. Использование strtok() хорошо в контексте, но выделение памяти является утечкой. Вы выделяете достаточно места для символьного указателя, а затем копируете указатель из strtok() поверх единственного указателя на выделенное пространство (таким образом, его утечка). Затем указатель копируется в arguments[total]. Следовательно, код можно упростить до:

else if (strcmp(commandCopy, get) == 0)
{
    char *ptr;
    int total = 0;
    char *arguments[1024];

    ptr = strtok(copy, " ");

    while (ptr != NULL)
    {
        arguments[total++] = ptr;
        ptr = strtok(NULL, " ");
    }

Номинально, должна быть проверка, чтобы вы не переполняли список arguments, но, поскольку оригинал ограничивает строку до 2000 символов, вы не можете иметь более 1000 аргументов (все одиночные символы разделяются одним пробелом) ).

То, что у вас есть, работает - оно выполняет то же самое задание в течение долгого времени, но теряет память невероятно.

0 голосов
/ 12 октября 2011

Основная проблема заключается в том, что сервер отправляет все содержимое, но не закрывает сокет, поэтому у клиента нет возможности узнать, что сервер сделал. Если вы закроете сокет после завершения отправки данных (или просто вызовите shutdown ()), то read () клиента вернет 0, когда завершит чтение данных.

FWIW, есть много других проблем с этим кодом:

  • getRequest: вы вызываете malloc, но никогда не бесплатно. На самом деле возвращаемое значение выбрасывается.
  • Зачем беспокоиться, если вы просто собираетесь ждать () ребенка?
  • Возможно, вы захотите использовать strlcpy вместо strpcy, чтобы избежать переполнения буфера.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...