Ошибка и неожиданное поведение с TCP-соединением - PullRequest
0 голосов
/ 15 октября 2010

Я хочу, чтобы мой TCP-сервер и клиент «общались» друг с другом в зависимости от того, что говорит другой. Но когда я запускаюсь, кажется, что он проходит одну итерацию, но тогда и сервер, и клиент, кажется, просто «зависают» там. Как только я убью его на стороне клиента, я получаю ошибку сломанной трубы.

Кто-нибудь может истолковать, что я здесь делаю неправильно?

Фрагмент кода СЕРВЕРА:

while(feof(file_ptr) == 0)
{
    fscanf(file_ptr, "%s", supplies);
    printf("%s\n", supplies);

    //SEND supplies to all clients (currently just one client)

    n = write(newsockfd, supplies, strlen(supplies));

    if (n < 0)
    {
        error("ERROR writing to socket");
    }


    //Receive a request from client that they can use supply

    bzero(buffer,2);
    n = read(newsockfd,buffer,2);

    if (n < 0)
    {
        error("ERROR reading from socket");
    }

    printf("Who is using supply? %s\n", buffer);


    if(strcmp(buffer, "A"))
    {
        aRounds++;  
    }


    while(done != 1)
    {
        //WAIT loop until message CO is received from client
        bzero(buffer,2);
        n = read(newsockfd,buffer,2);

        if (n < 0)
        {
            error("ERROR reading from socket");
        }

        printf("Done? %s\n", buffer);



        if(strcmp(buffer, "CO"))
        {
            done = 1;
        }
    }

    done = 0;
}

fclose(file_ptr);
n = write(newsockfd, "DN", 2);

Фрагмент кода КЛИЕНТА:

while(noSupplies != 1)
{
    //RECEIVE MSG from server about supplies
    bzero(buffer,2); 
    n = read(sockfd,buffer,2);

    if (n < 0) 
    {
        error("ERROR reading from socket");
    }

    printf("%s\n",buffer);

    if(strcmp(buffer, "BC") == 0 || strcmp(buffer, "CB") == 0)
    {
        //SEND server msg that you are using supply

        n = write(sockfd,"A", 1);
        if (n < 0)
        {
            error("ERROR writing to socket"); 
        }


        printf("Client A has received components %s during round %d.\n", buffer, round);


        n = write(sockfd,"CO", 2);
        if (n < 0)
        {
            error("ERROR writing to socket"); 
        }

    }
    else if(strcmp(buffer, "DN"))
    {
        noSupplies = 1;
    }

    round++;
}

Я получаю с сервера следующее (до убийства):

BC
Who is smoking? A
Done smoking? CO

И следующее от клиента (до убийства):

BC
Client A has received components BC during round 1.

Затем после убийства с клиента .. Я получаю с сервера следующее:

BC
Who is using supply? A
Done? CO
Done? 
CB
Who is using supply? 
Done? 
CB
Who is using supply? 
Done? 
BC
Broken pipe

Кто-нибудь понимает, что я делаю неправильно? (ищет исправление кода!)

Просто к вашему сведению ... Я буду со временем менять код сервера для обработки прослушивания нескольких клиентов (TCP), но по одному препятствию за раз, верно? : S

Спасибо!

Ответы [ 2 ]

1 голос
/ 15 октября 2010

Не уверен, что это все из-за вашей проблемы, но

bzero(buffer, 2);
n = read(socket, buffer, 2);

...

printf("%s", buffer);

неверно, так как если чтение действительно получило 2 байта, и ни один из них не был равен 0, то буфер может не быть строкой с нулевым символом в конце (если ранее не было чего-то такого).

Несколько вызовов strcmp также всегда должны завершаться неудачей по одной и той же причине - чтение в строке не завершается 0, поэтому strcmp считает, что оно продолжается и, следовательно, не совпадает с строкой сравнения, даже если первые буквы одинаковы.

1012 * редактировать * n = read(socket, buffer, 2); if (n<0) { die_horrible_death(); } buffer[n] = 0; // since arrays are 0 indexed this should be after last read character printf("I just read: \"%s\"\n", buffer);

0 голосов
/ 15 октября 2010

Ваш серверный код сначала записывает что-то клиенту, в начале. Позже, в цикле - он просто читает.

OTOH ваш клиент читает и пишет в цикле.

Поскольку вы работаете с сокетами в режиме блокировки - это означает, что ваш клиент в конечном итоге будет заблокирован при вызове recv.

P.S. Без обид - но вам есть чему поучиться.

  1. TCP - это туннель. Когда ваш сервер отправляет 2 байта данных за один вызов send / write - нет никакой гарантии, что ваш клиент прочитает это за один вызов recv.
  2. Следовательно - чтение и анализ всегда должны выполняться в виде цикла.
  3. Вы не можете написать действительно надежный клиент / сервер с возможностью тайм-аута / прерывания по требованию, используя только блокирующий ввод / вывод.
  4. Учиться, учиться, учиться
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...