Как мне перевести функцию recv () в c ++? - PullRequest
4 голосов
/ 14 июля 2011

У меня есть программа, работающая на сервере, взаимодействующая с другой программой, работающей на клиенте. Они оба отправляют данные и файлы туда и обратно.

Я заметил, что всякий раз, когда есть socHandler.read () (функция для чтения данных, поступающих в сокет), он застревает в ожидании поступления данных.

Так выглядит функция.

int CSocHandler::read(char * inBuffer, INT64 iBytesToRead){

    bool blReadMore=false;
    int retVal = 0;

    int iOutputPointer = 0;


    do{
        blReadMore = false;
        if (iStartOfBuffer == iEndOfBuffer) {   //Buffer empty
            if (blClosed ) {
                return -1;
            }
            iStartOfBuffer = 0;
            iEndOfBuffer = 0;
            size_t bufferRemaining = BUFFER_SIZE-iEndOfBuffer;
                        int bytesRecvd = recv( sock, &buffer[iEndOfBuffer], (int)iBytesToRead<bufferRemaining?iBytesToRead:bufferRemaining), 0 );   
            if ( bytesRecvd <= 0) {
                close();
                Yield();
                return retVal;
            }
        }
    } while(blReadMore);

    return retVal;
  }

Переменная sock является типом SOCKET и является глобальной переменной, определенной в другом месте. Как я могу установить параметры или сделать этот вызов recv () неблокирующим только для этого вызова функции и не влиять на другие функции?

Я полагаю, что это то место, где оно застревает в ожидании данных, и я хочу, чтобы оно истекло через X секунд.

Ответы [ 2 ]

3 голосов
/ 14 июля 2011

Вызовите select(), чтобы узнать, есть ли в сокете какие-либо ожидающие данные, а затем вызовите recv(), чтобы прочитать их.

3 голосов
/ 14 июля 2011

Используйте select(2) на сокете до recv.

При использовании синтаксиса Perl это будет выглядеть так:

sub read_with_timeout {
   my ($sock, $bytes_to_read, $timeout) = @_;

   my $sel = IO::Select->new($sock);
   my $end_time = Time::HiRes::time() + $timeout;

   my $buf = '';
   while ($bytes_to_read) {
      $timeout >= 0 && () = $sel->can_read($timeout);
         or die("Timeout");

      my $rv = sysread($sock, $buf, $bytes_to_read, length($buf));
      die "read: $!" if !defined($rv);
      die "Premature eof" if !$rv;

      $bytes_to_read -= $rv;

      $timeout = $end_time - Time::HiRes::time();
   }

   return $buf;
}

can_read - это вызов select(2).

...