URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 5457
[ Назад ]

Исходное сообщение
"Socket - Передача файлов"

Отправлено NikR , 27-Май-06 04:05 
Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.

Содержание

Сообщения в этом обсуждении
"Socket - Передача файлов"
Отправлено ACCA , 27-Май-06 11:39 
В смысле из буфера `write'? man fflush, fsync, хотя разумеется не гарантируется, что оно вообще дойдёт.

Ещё можно пользоваться `send'.


"Socket - Передача файлов"
Отправлено smb , 28-Май-06 01:39 
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>

Какого еще конца файла??
Чтобы ОС отправила по TCP данные, находящиеся в output buffer(помещаются очевидно через send() | write()), надо, чтобы...На последние пакеты должно прийти подтверждение = ACK, чтобы она могла убрать отосланные и подтвержденные данные из буфера...Тогда отошлются следующие данные....(на самом деле, всё гораздо сложнее, но идея - на все данные должно прийти подтверждение - тогда начнут отправляться новые данные)

Сервер-то где подвисает?В read()?


"Socket - Передача файлов"
Отправлено NikR , 29-Май-06 02:00 
>>Подскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>
>
>Какого еще конца файла??
>Чтобы ОС отправила по TCP данные, находящиеся в output buffer(помещаются очевидно через
>send() | write()), надо, чтобы...На последние пакеты должно прийти подтверждение =
>ACK, чтобы она могла убрать отосланные и подтвержденные данные из буфера...Тогда
>отошлются следующие данные....(на самом деле, всё гораздо сложнее, но идея -
>на все данные должно прийти подтверждение - тогда начнут отправляться новые
>данные)
>
>Сервер-то где подвисает?В read()?


>Да. Именно в read().

Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться, тогда те куски приходят без проблем.
Идея понятна. Но как реализовать?


"Socket - Передача файлов"
Отправлено niknik , 29-Май-06 13:48 
При организации TCP сессии даные не могут быть потеряны, т.е. пока не прийдет подтверждение о доставке предыдущего сообщения, следующее не посылается. Если связь организована c использованием UDP так он и не гарантирует доставку без ошибок.
На основе какого метода конкретно происходит общение клиента и сервера ???

"Socket - Передача файлов"
Отправлено NikR , 30-Май-06 01:51 
>При организации TCP сессии даные не могут быть потеряны, т.е. пока не
>прийдет подтверждение о доставке предыдущего сообщения, следующее не посылается. Если связь
>организована c использованием UDP так он и не гарантирует доставку без
>ошибок.
>На основе какого метода конкретно происходит общение клиента и сервера ???

>Использую TCP соединение.
Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается close () или shutdown(). Понятное дело, всё работает. А вот интересно если сервер и клиент работают определённое время, за которое необходимо передать N файлов.
Как не допустить зависание сервера на read()?  


"Socket - Передача файлов"
Отправлено niknik , 30-Май-06 10:27 
> Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается
>close () или shutdown(). Понятное дело, всё работает. А вот интересно
>если сервер и клиент работают определённое время, за которое необходимо передать
>N файлов.
>Как не допустить зависание сервера на read()?

Необходимо анализировать результат функции read(), При этом сервер может находится как в блокирущем так и не в блокирующем режиме(WAIT/NOWAIT). Для того чтобы сервер не зависал используй неблокирующий режим.  


"Socket - Передача файлов"
Отправлено NikR , 01-Июн-06 01:28 
>> Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается
>>close () или shutdown(). Понятное дело, всё работает. А вот интересно
>>если сервер и клиент работают определённое время, за которое необходимо передать
>>N файлов.
>>Как не допустить зависание сервера на read()?
>
>Необходимо анализировать результат функции read(), При этом сервер может находится как в
>блокирущем так и не в блокирующем режиме(WAIT/NOWAIT). Для того чтобы сервер
>не зависал используй неблокирующий режим.

>Как избежать зависание я представляю. При неблокирующем режиме очень тяжело
следить за буфером, правильной его выборкой.
Я не понимаю, почему клиент остовляет часть данных у себя. И только если на его стороне закрыть соединение достовляются. Можно как нибудь без закрытия, что то типа flush()..?



"Socket - Передача файлов"
Отправлено Serega_S , 05-Июн-06 03:11 
>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>тогда те куски приходят без проблем.
>Идея понятна. Но как реализовать?

Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё данных в буфер, т.е. данные отсылаются одним большим куском, или же по истечении некоторого времени, которое может быть довольно большим.

Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():

setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));


"Socket - Передача файлов"
Отправлено NikR , 05-Июн-06 10:23 
>>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>>тогда те куски приходят без проблем.
>>Идея понятна. Но как реализовать?
>
>Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо
>отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких
>пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную
>способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё
>данных в буфер, т.е. данные отсылаются одним большим куском, или же
>по истечении некоторого времени, которое может быть довольно большим.
>
>Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():
>
>setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));



"Socket - Передача файлов"
Отправлено NikR , 05-Июн-06 10:27 
>>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>>тогда те куски приходят без проблем.
>>Идея понятна. Но как реализовать?
>
>Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо
>отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких
>пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную
>способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё
>данных в буфер, т.е. данные отсылаются одним большим куском, или же
>по истечении некоторого времени, которое может быть довольно большим.
>
>Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():
>
>setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));

Это конечно всё хорошо. Но я сомневаюсь, что с подобной проблемой, боряться таким образом.
Как говориться это уже в крайнем случае. Да и идея у меня не в том что бы без задержек передовать данные, а чтоб последний фрагмент доставить.
  Спасибо.


"Socket - Передача файлов"
Отправлено Serega_S , 07-Июн-06 03:29 
>Это конечно всё хорошо. Но я сомневаюсь, что с подобной проблемой, боряться
>таким образом.
>Как говориться это уже в крайнем случае. Да и идея у меня
>не в том что бы без задержек передовать данные, а чтоб
>последний фрагмент доставить.

1) Если вы больше не будете передавать данные по сокету - закрываейте его - данные передадуться оставшиеся в буфере передачи.
2) Если ожидается ещё передавать данные по этому сокету - ждите ещё блока данных - он вытолкнет буфер - т.е. логика работы не нарушается.
3) Если важно именно "сразу" получить данные, т.к. следующий может прийти через 3 дня к примеру, то это как раз проблема временная, которая решается отключением алгоритма Нигла.
4) Если есть проблема в "зависании" приёмной стороны - делайте или неблокируемый сокет или же многопоточное приложение.

P.S. Какого либо решения наподобии fflush() для сокета я не знаю, если оно есть - будет интересно услышать.


"Socket - Передача файлов"
Отправлено NuINu , 30-Май-06 16:53 
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>

Скорее всего у теб какой то глюк или ошибка в клиенте....

А что бы сервер не зависал на чтении надо использовать select с установкой таймаута


"Socket - Передача файлов"
Отправлено NikR , 01-Июн-06 01:33 
>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>
>
>Скорее всего у теб какой то глюк или ошибка в клиенте....
>
>А что бы сервер не зависал на чтении надо использовать select с
>установкой таймаута


Буду ждать новых предложений...


"Socket - Передача файлов"
Отправлено chip , 01-Июн-06 02:15 
>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>>
>>
>>Скорее всего у теб какой то глюк или ошибка в клиенте....
>>
>>А что бы сервер не зависал на чтении надо использовать select с
>>установкой таймаута
>
>
>Буду ждать новых предложений...

Если есть возможность разместите код клиент-сервера. Это упростит задачу.



"Socket - Передача файлов"
Отправлено NikR , 02-Июн-06 02:19 
>>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>>>
>>>
>>>Скорее всего у теб какой то глюк или ошибка в клиенте....
>>>
>>>А что бы сервер не зависал на чтении надо использовать select с
>>>установкой таймаута
>>
>>
>>Буду ждать новых предложений...
>
>Если есть возможность разместите код клиент-сервера. Это упростит задачу.

Сервер принимает файл:

int filein (char *pathf,int fd) {
int n;
FILE *f;
char buf[MAX_PATCH_LEN];

if ((f=fopen(pathf,"w+"))==NULL)
  {
   return (-1);
  }
  while ((n=read(fd,&buf,sizeof(buf)))>0) {   //Здесь мы очень долго ждём
   if (fwrite(buf,1,n,f)<0)
     {    
       fclose (f);
       return (-1);
     }
  }
fclose (f);
}


Клиент использует функцию для передачи файла:

int fileto (char *pathf,int fd) {
int n;
FILE *f;
char buf[MAX_PATCH_LEN];

if ((f=fopen(pathf,"r"))==NULL)
  {
   return (-1);
  }
  
  while ((n=fread(&buf,1,sizeof(buf),f))!=NULL) {
   if (write(fd,buf,n)<0)
     {
       return (-1);
     }
  }
shutdown (fd,2);  //Если без этого, то сервер так и не получит последних данных
                  //находящихся у клиента.
}


"Socket - Передача файлов"
Отправлено chip , 03-Июн-06 15:25 
>>>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>>>>
>>>>
>>>>Скорее всего у теб какой то глюк или ошибка в клиенте....
>>>>
>>>>А что бы сервер не зависал на чтении надо использовать select с
>>>>установкой таймаута
>>>
>>>
>>>Буду ждать новых предложений...
>>
>>Если есть возможность разместите код клиент-сервера. Это упростит задачу.
>
>Сервер принимает файл:
>
>int filein (char *pathf,int fd) {
>int n;
>FILE *f;
>char buf[MAX_PATCH_LEN];
>
>if ((f=fopen(pathf,"w+"))==NULL)
>  {
>   return (-1);
>  }

почему бы здесь не вставить select?

>  while ((n=read(fd,&buf,sizeof(buf)))>0) {   //Здесь мы очень долго ждём

может read заменить на recv/recvfrom?

>   if (fwrite(buf,1,n,f)<0)
>     {
>       fclose (f);
>    return (-1);
>     }
>  }
>fclose (f);
>}
>
>
>
>
>Клиент использует функцию для передачи файла:
>
>int fileto (char *pathf,int fd) {
>int n;
>FILE *f;
>char buf[MAX_PATCH_LEN];
>
>if ((f=fopen(pathf,"r"))==NULL)
>  {
>   return (-1);
>  }
>
>  while ((n=fread(&buf,1,sizeof(buf),f))!=NULL) {
>   if (write(fd,buf,n)<0)

write -> send

>     {
>    return (-1);
>     }
>  }
>shutdown (fd,2);  //Если без этого, то сервер так и не получит
>последних данных
>            
>      //находящихся у клиента.
>}



"Socket - Передача файлов"
Отправлено NikR , 04-Июн-06 01:12 
Спасибо.
*-
Обязательно попробую данный вариант. Но только не пойму принципиальной разници.
Разве что, send/recv использовать определённые флаги. А таимаут в select спасёт только от завизание сервером, но данные так и не дополучу.



"Socket - Передача файлов"
Отправлено NikR , 09-Июн-06 05:31 
Да, я понял Вашу идею.
Но вопрос остаётся открытым..
А именно: "Каким образом можно (без отключения алгоритма Нигла) доставить эти дурацкие данные, которые томятся у клиента" ?

Надо наверное сворачивать эту тему, а то скорее всего я Вам всем поднадоел.
Но думается проблема актуальная.


"Socket - Передача файлов"
Отправлено Serega_S , 09-Июн-06 07:24 
>Да, я понял Вашу идею.
>Но вопрос остаётся открытым..
>А именно: "Каким образом можно (без отключения алгоритма Нигла) доставить эти дурацкие
>данные, которые томятся у клиента" ?
>
>Надо наверное сворачивать эту тему, а то скорее всего я Вам всем
>поднадоел.
>Но думается проблема актуальная.

Согласен, вопрос остаётся открытым. И было бы хорошо, если бы кто-нибудь на него ответил.

Хотя я не уверен, что есть средства вмешательства во внутреннюю логику tcp-протокола. Т.е. фактически дублирование алгоритма Нигла.

А гибкий механизм управления типа fflush был бы, конечно, приятен...


"Socket - Передача файлов"
Отправлено NikR , 10-Июн-06 02:17 
>А гибкий механизм управления типа fflush был бы, конечно, приятен...

Ещё один маленький вопрос.
Попытка вырубить алгоритм Нигла:

setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,(char *) &option, sizeof(option));

В результате он не отключается.


"Socket - Передача файлов"
Отправлено serge , 11-Июн-06 15:43 
>>А гибкий механизм управления типа fflush был бы, конечно, приятен...
>
>Ещё один маленький вопрос.
>Попытка вырубить алгоритм Нигла:
>
>setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,(char *) &option, sizeof(option));
>
>В результате он не отключается.

потому, что вы делаете что-то другое ))
нужно так:

   int on = 1;

   if (-1 == setsockopt(fd, SOL_TCP, TCP_NODELAY, (void *) &on, sizeof (on)))
        warn("setsockopt(TCP_NODELAY)");


"Socket - Передача файлов"
Отправлено cobold , 12-Июн-06 03:08 
При такой постановке задачи почему бы не использовать sendfile(2) ?

>
>Сервер принимает файл:
>
>int filein (char *pathf,int fd) {
>int n;
>FILE *f;
>char buf[MAX_PATCH_LEN];
>
>if ((f=fopen(pathf,"w+"))==NULL)
>  {
>   return (-1);
>  }
>  while ((n=read(fd,&buf,sizeof(buf)))>0) {   //Здесь мы очень долго ждём
>   if (fwrite(buf,1,n,f)<0)
>     {
>       fclose (f);
>    return (-1);
>     }
>  }
>fclose (f);
>}
>
>
>
>
>Клиент использует функцию для передачи файла:
>
>int fileto (char *pathf,int fd) {
>int n;
>FILE *f;
>char buf[MAX_PATCH_LEN];
>
>if ((f=fopen(pathf,"r"))==NULL)
>  {
>   return (-1);
>  }
>
>  while ((n=fread(&buf,1,sizeof(buf),f))!=NULL) {
>   if (write(fd,buf,n)<0)
>     {
>    return (-1);
>     }
>  }
>shutdown (fd,2);  //Если без этого, то сервер так и не получит
>последних данных
>            
>      //находящихся у клиента.
>}



"Socket - Передача файлов"
Отправлено serge , 11-Июн-06 15:39 
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>

после того, как сделали send/write на отправляющей стороне, сделайте read/recv там-же. данные будут вытолкнуты из буффера и отправлены принимающей стороне.

кроме того, можно попробовать включить и сразу выключить флаг TCP_CORK, что-то типа:

    int on = 1, off = 0;

    if (-1 == setsockopt(fd, SOL_TCP, TCP_CORK, (void *) &on, sizeof(on)))
        warn("setsockopt(TCP_CORK)");

    if (-1 == setsockopt(fd, SOL_TCP, TCP_CORK, (void *) &off, sizeof(off)))
        warn("setsockopt(TCP_CORK)");

но этот способ только для Linux.

далее - философские рассуждения )
вообще, мне кажется, нужно сразу делать эти вещи в неблокирующем режиме. простота блокирующего режима - мнимая.


"Socket - Передача файлов"
Отправлено NikR , 13-Июн-06 02:20 
>далее - философские рассуждения )
>вообще, мне кажется, нужно сразу делать эти вещи в неблокирующем режиме. простота
>блокирующего режима - мнимая.


Что то не слышел о TCP_CORK, но какие мои годы.
Может переводить сокет в неблокирующи, а затем обратно?
Тем самым доставлю данные.
Ну и конечно проверю Ваш метод


"Socket - Передача файлов"
Отправлено vlad , 16-Июн-06 10:40 
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>

У меня аналогичная проблема решилась так:

Передающая сторона int val = 0;setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));

Принимающая сторона через select()