2012-01-16 2 views
1

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

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; 

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

while(readtar){ 

    senddata 
    get processed data 
} 

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

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

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

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

БЕЗ ВЫБОР

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); 
} 

Так .. если отправленные данные не достаточно, чтобы произвести на Если бы я мог проверить, если прочитать ничего или на сторону стандартного ввода, если послать эти функции имеют терминатор, я мог бы решить эту проблему

ответ

4

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

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

+0

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

+0

Проблема в том, когда мне нужно подождать данные, потому что она не отправляет ok в этот цикл. Для меня данные могут иметь любой размер, но если в том же цикле я отправляю его, не отправляйте данные обратно, у меня есть проблема, потому что recv должен получить данные обратно. – Lefsler

+0

"или 0, если вы используете неблокирующий ввод-вывод" - на самом деле recv вернет -1, если неблокирующие сокеты не имеют доступных данных (а errno будет EAGAIN или EWOULDBLOCK). 0 возвращается только для указания, что удаленная сторона закрыла или выключила его конец. – selbie