Выберите на сокете путается с данными - PullRequest
1 голос
/ 16 января 2012

Я отправляю некоторые данные через сокет, но мне нужно установить время ожидания.Я использую что-то вроде:

fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(sockDesc, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(sockDesc + 1, &rfds, NULL, NULL, &tv);
if(rtn = ::recv(sockDesc, (raw_type*) buffer, bufferLen, 0)) < 0){
throw SocketException("error", true);
}
return rtn;

Итак.В зависимости от типа данных, которые я возвращаю, мне нужно реализовать таймаут или нет.Если я просто отправляю текстовые данные, которые мне не нужны, если я отправляю один файл, который мне нужен ...Чтобы объяснить более или менее, я отправляю некоторые данные через сокет и обрабатываю на другой стороне.Итак, если я отправлю один tar:

while(readtar){

  senddata
  get processed data
}

но иногда отправляемые данные являются просто заголовком, поэтому, когда другая сторона обрабатывает данные, ей не нужно возвращать данные, и сокет останавливается на чтение.Для иллюстрации: cat file.tar |myprogram -c "tar -zvt"

Таким образом, он ничего не возвращает, пока не получит достаточно данных для возврата имени файла.

Если я просто отправляю один файл и возвращаю "cat", у меня нет этой проблемыэхо "asjdoiajdlaijdkasdjlkas" |myprogram -c "кошка"или жекот HUGEFILE.tar |myprogram -c "кошка" |tar -zvtВ этом случае он делает то же самое, но не на стороне сервера ... поэтому он не работает для меня.

Теперь .... Если я просто использую recv без выбора, когда возвращаю данные с помощью cat, это работает ... никаких проблем с этим.НО, если я реализую выбор, данные будут испорчены

БЕЗ ВЫБРАТЬ

send "command line text temp test"
recv "command line text temp test"

С

send "command line text temp test"
recv "commmand lin/ˆ
1k5d99ck"

Это просто для иллюстрации того, что происходит

Цикл клиента:

while(size = read(fileno(stdin), thebuffer, 10000)){
  sock->send(thebuffer, size); // if this data is not enough the other side never sends the data back
  sock->recv //receive data
}

С другой стороны я делаю

if(pid == 0){
//stuffs closes, dup2
execlp("bash", "bash", "-c", "run.c_str(), NULL); // if i use one tar -zvt i need a bunch of data to generate the return
  }
else
while(size = read(fout[0], buffer, 10000) > 0)){
  sock->send(buffer, size);
}

Итак ... если отправленных данных недостаточно для генерации Если я могу проверить, есть ли что-то для чтения или на стороне стандартного ввода, если execlp отправляет терминатор Iможет решить проблему

1 Ответ

4 голосов
/ 16 января 2012

Звучит так, как будто вы ожидаете, что ваш TCP recv () вернет вам данные кусками определенного размера ... однако TCP recv () не работает таким образом. TCP основан на потоке, поэтому число байтов, возвращаемых recv (), может варьироваться от 1 (или 0, если вы используете неблокирующий ввод / вывод) до размера буфера, который вы передали. получение кода для зацикливания при необходимости для повторной конкатенации полученных данных.

Кроме того, похоже, что вы пытаетесь распечатать неоконченные строки ASCII - это объясняет символы мусора в конце вашего второго примера recv (). (т.е. если вы хотите распечатать полученные байты данных в виде строки, обязательно поместите байт NUL / 0 после последнего полученного байта; recv () не сделает этого за вас)

...