Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
В смысле из буфера `write'? man fflush, fsync, хотя разумеется не гарантируется, что оно вообще дойдёт.Ещё можно пользоваться `send'.
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>Какого еще конца файла??
Чтобы ОС отправила по TCP данные, находящиеся в output buffer(помещаются очевидно через send() | write()), надо, чтобы...На последние пакеты должно прийти подтверждение = ACK, чтобы она могла убрать отосланные и подтвержденные данные из буфера...Тогда отошлются следующие данные....(на самом деле, всё гораздо сложнее, но идея - на все данные должно прийти подтверждение - тогда начнут отправляться новые данные)Сервер-то где подвисает?В read()?
>>Подскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>
>
>Какого еще конца файла??
>Чтобы ОС отправила по TCP данные, находящиеся в output buffer(помещаются очевидно через
>send() | write()), надо, чтобы...На последние пакеты должно прийти подтверждение =
>ACK, чтобы она могла убрать отосланные и подтвержденные данные из буфера...Тогда
>отошлются следующие данные....(на самом деле, всё гораздо сложнее, но идея -
>на все данные должно прийти подтверждение - тогда начнут отправляться новые
>данные)
>
>Сервер-то где подвисает?В read()?
>Да. Именно в read().Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться, тогда те куски приходят без проблем.
Идея понятна. Но как реализовать?
При организации TCP сессии даные не могут быть потеряны, т.е. пока не прийдет подтверждение о доставке предыдущего сообщения, следующее не посылается. Если связь организована c использованием UDP так он и не гарантирует доставку без ошибок.
На основе какого метода конкретно происходит общение клиента и сервера ???
>При организации TCP сессии даные не могут быть потеряны, т.е. пока не
>прийдет подтверждение о доставке предыдущего сообщения, следующее не посылается. Если связь
>организована c использованием UDP так он и не гарантирует доставку без
>ошибок.
>На основе какого метода конкретно происходит общение клиента и сервера ???>Использую TCP соединение.
Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается close () или shutdown(). Понятное дело, всё работает. А вот интересно если сервер и клиент работают определённое время, за которое необходимо передать N файлов.
Как не допустить зависание сервера на read()?
> Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается
>close () или shutdown(). Понятное дело, всё работает. А вот интересно
>если сервер и клиент работают определённое время, за которое необходимо передать
>N файлов.
>Как не допустить зависание сервера на read()?Необходимо анализировать результат функции read(), При этом сервер может находится как в блокирущем так и не в блокирующем режиме(WAIT/NOWAIT). Для того чтобы сервер не зависал используй неблокирующий режим.
>> Во всех примерах клиент-сервер, которые я видел, любой обмен данными заканчивается
>>close () или shutdown(). Понятное дело, всё работает. А вот интересно
>>если сервер и клиент работают определённое время, за которое необходимо передать
>>N файлов.
>>Как не допустить зависание сервера на read()?
>
>Необходимо анализировать результат функции read(), При этом сервер может находится как в
>блокирущем так и не в блокирующем режиме(WAIT/NOWAIT). Для того чтобы сервер
>не зависал используй неблокирующий режим.>Как избежать зависание я представляю. При неблокирующем режиме очень тяжело
следить за буфером, правильной его выборкой.
Я не понимаю, почему клиент остовляет часть данных у себя. И только если на его стороне закрыть соединение достовляются. Можно как нибудь без закрытия, что то типа flush()..?
>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>тогда те куски приходят без проблем.
>Идея понятна. Но как реализовать?Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё данных в буфер, т.е. данные отсылаются одним большим куском, или же по истечении некоторого времени, которое может быть довольно большим.
Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():
setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));
>>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>>тогда те куски приходят без проблем.
>>Идея понятна. Но как реализовать?
>
>Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо
>отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких
>пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную
>способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё
>данных в буфер, т.е. данные отсылаются одним большим куском, или же
>по истечении некоторого времени, которое может быть довольно большим.
>
>Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():
>
>setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));
>>Передаётся небольшая структура. При аналезе (tcpdump..) выяснелось, что пару фрагментов
>>остаются на клинтской части. Обидно. Приходиться закрывать соединение, а затем вновь подключаться,
>>тогда те куски приходят без проблем.
>>Идея понятна. Но как реализовать?
>
>Если есть необходимость передавать данные без задержек по tcp протоколу, то необходимо
>отключить алгоритм Нигла в сокете. Этот алгоритм предотвращает большое количество мелких
>пакетов в сети, которые излишне нагружают сеть и уменьшают её пропускную
>способность. Этот алгоритм предотвращает посылку мелких пакетов путём ожидания добавление ещё
>данных в буфер, т.е. данные отсылаются одним большим куском, или же
>по истечении некоторого времени, которое может быть довольно большим.
>
>Чтобы отклюсить этот алгоритм, необходимо после создания сокета функцией socket():
>
>setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char*)&t,sizeof(t));Это конечно всё хорошо. Но я сомневаюсь, что с подобной проблемой, боряться таким образом.
Как говориться это уже в крайнем случае. Да и идея у меня не в том что бы без задержек передовать данные, а чтоб последний фрагмент доставить.
Спасибо.
>Это конечно всё хорошо. Но я сомневаюсь, что с подобной проблемой, боряться
>таким образом.
>Как говориться это уже в крайнем случае. Да и идея у меня
>не в том что бы без задержек передовать данные, а чтоб
>последний фрагмент доставить.1) Если вы больше не будете передавать данные по сокету - закрываейте его - данные передадуться оставшиеся в буфере передачи.
2) Если ожидается ещё передавать данные по этому сокету - ждите ещё блока данных - он вытолкнет буфер - т.е. логика работы не нарушается.
3) Если важно именно "сразу" получить данные, т.к. следующий может прийти через 3 дня к примеру, то это как раз проблема временная, которая решается отключением алгоритма Нигла.
4) Если есть проблема в "зависании" приёмной стороны - делайте или неблокируемый сокет или же многопоточное приложение.P.S. Какого либо решения наподобии fflush() для сокета я не знаю, если оно есть - будет интересно услышать.
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>Скорее всего у теб какой то глюк или ошибка в клиенте....
А что бы сервер не зависал на чтении надо использовать select с установкой таймаута
>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>
>
>Скорее всего у теб какой то глюк или ошибка в клиенте....
>
>А что бы сервер не зависал на чтении надо использовать select с
>установкой таймаута
Буду ждать новых предложений...
>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>>>
>>
>>Скорее всего у теб какой то глюк или ошибка в клиенте....
>>
>>А что бы сервер не зависал на чтении надо использовать select с
>>установкой таймаута
>
>
>Буду ждать новых предложений...Если есть возможность разместите код клиент-сервера. Это упростит задачу.
>>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>>передачи. А то сервер подвисает, ждёт конца файла. 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); //Если без этого, то сервер так и не получит последних данных
//находящихся у клиента.
}
>>>>>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>>>>>передачи. А то сервер подвисает, ждёт конца файла. 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); //Если без этого, то сервер так и не получит
>последних данных
>
> //находящихся у клиента.
>}
Спасибо.
*-
Обязательно попробую данный вариант. Но только не пойму принципиальной разници.
Разве что, send/recv использовать определённые флаги. А таимаут в select спасёт только от завизание сервером, но данные так и не дополучу.
Да, я понял Вашу идею.
Но вопрос остаётся открытым..
А именно: "Каким образом можно (без отключения алгоритма Нигла) доставить эти дурацкие данные, которые томятся у клиента" ?Надо наверное сворачивать эту тему, а то скорее всего я Вам всем поднадоел.
Но думается проблема актуальная.
>Да, я понял Вашу идею.
>Но вопрос остаётся открытым..
>А именно: "Каким образом можно (без отключения алгоритма Нигла) доставить эти дурацкие
>данные, которые томятся у клиента" ?
>
>Надо наверное сворачивать эту тему, а то скорее всего я Вам всем
>поднадоел.
>Но думается проблема актуальная.Согласен, вопрос остаётся открытым. И было бы хорошо, если бы кто-нибудь на него ответил.
Хотя я не уверен, что есть средства вмешательства во внутреннюю логику tcp-протокола. Т.е. фактически дублирование алгоритма Нигла.
А гибкий механизм управления типа fflush был бы, конечно, приятен...
>А гибкий механизм управления типа fflush был бы, конечно, приятен...Ещё один маленький вопрос.
Попытка вырубить алгоритм Нигла:setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,(char *) &option, sizeof(option));
В результате он не отключается.
>>А гибкий механизм управления типа 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)");
При такой постановке задачи почему бы не использовать 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); //Если без этого, то сервер так и не получит
>последних данных
>
> //находящихся у клиента.
>}
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. 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.
далее - философские рассуждения )
вообще, мне кажется, нужно сразу делать эти вещи в неблокирующем режиме. простота блокирующего режима - мнимая.
>далее - философские рассуждения )
>вообще, мне кажется, нужно сразу делать эти вещи в неблокирующем режиме. простота
>блокирующего режима - мнимая.
Что то не слышел о TCP_CORK, но какие мои годы.
Может переводить сокет в неблокирующи, а затем обратно?
Тем самым доставлю данные.
Ну и конечно проверю Ваш метод
>Аодскажите пожалуйста, какие есть способы доставки клиентом серверу данных находящихся в буфере
>передачи. А то сервер подвисает, ждёт конца файла. TCP_NONDELAY не помогает.
>У меня аналогичная проблема решилась так:
Передающая сторона int val = 0;setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
Принимающая сторона через select()