Как я могу прочитать произвольно большой файл в сокет TCP в C? - PullRequest
1 голос
/ 07 февраля 2012

Я только изучаю программирование сокетов и пытаюсь написать эхо-клиент, который читает из stdin и пишет в сокет, а затем читает ответ сервера из сокета в стандартный вывод.Проблема в том, что я не знаю, как долго будет stdin или как долго будет отклик сервера.Код, который я пытаюсь использовать, выглядит следующим образом (создание сокета и подключение к серверу не включены):

length = BUF_SIZE;
while (length == BUF_SIZE) {  // length will equal BUF_SIZE if buf is full, when length < BUF_SIZE we have reached an EOF                                 
   // Reads from STDIN to buf                                                                                                                              
   if ((length = read(STDIN_FILENO, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error in reading from STDIN");
     return 4;
   }
   // Writes from buf to the socket                                                                                                                        
   if ((write(sock, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error writing to socket");
     return 5;
   }
 }

if ((status = shutdown(sock, 1)) < 0){ // Shuts down socket from doing more receives                                                                      
   fprintf(stderr, "Error shutting down socket for writing");
   return 6;
}

length = BUF_SIZE; 
while (length == BUF_SIZE){
   // Read from socket to buf                                                                                                                              
   if ((length = read(sock, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error reading from socket");
     return 7;
   }
   // Write from buf to STDOUT                                                                                                                             
   if ((write(STDOUT_FILENO, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error writing to STDOUT");
     return 8;
   }
}

close(sock);
exit(0);

BUF_SIZE определяется как 100. Когда я запускаю свою программу, программа обычно подключается ксервер и отправляет правильное сообщение, но то, что он пишет в stdout, является либо ничем, либо бессмысленным.

Что я делаю не так?

1 Ответ

1 голос
/ 07 февраля 2012

Ваш цикл while будет работать только в первый раз. read () / write () будут возвращать только ту сумму, которую они на самом деле читают / пишут, которая может быть не равна BUF_SIZE. Допустим, вы прочитали десять байтов из сокета, а затем записали сто в стандартный вывод - последние 90 будут мусором.

Что-то в этом роде приблизит вас к тому, что вы хотите.

while (1)
{
    if ((length = read(STDIN_FILENO, buf, BUF_SIZE)) < 0)
    {
        fprintf(stderr, "Error in reading from STDIN");
        return 4;
    }

    if ((write(sock, buf, length)) < 0)
    {
        fprintf(stderr, "Error writing to socket");
        return 5;
    }

    if ((length = read(sock, buf, BUF_SIZE)) < 0)
    {
        fprintf(stderr, "Error reading from socket");
        return 7;
    }

    if ((write(STDOUT_FILENO, buf, length)) < 0)
    {
        fprintf(stderr, "Error writing to STDOUT");
        return 8;
    }
}
...