Синхронность в TCP/IP
От: Шебеко Евгений  
Дата: 24.07.09 09:42
Оценка:
Конечно странно слышать такой вопрос от человека, который около 10 лет
программирует, но увы

Имеем передачу данных по соединению TCP/IP от A->B.
Вопрос имеются ли в TCP/IP механизмы, поддерживающие синхронность передачи?

Поясню:

1. A постоянно посылает большой объём данных.
2. B успевает принять, но не успевает обработать такой объем (к примеру записать в БД)
3. Что произойдёт? Процесс в A заблокируется на send() или обломится на send()?

Если механизм существует, то просьба объяснить на пальцах как это происходит
или ткнуть в конкретное место, это объясняющее.
Re: Синхронность в TCP/IP
От: stbzh  
Дата: 24.07.09 10:49
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Конечно странно слышать такой вопрос от человека, который около 10 лет

Вдвойне странен такой вопрос от человека, который в соседней ветке советует смело отключать Нагла во всех приложениях.
Или я не понял всю глубину вопроса. Ну попытаюсь ответить.

Итак, у "В" не хватает ресурсов выбрать из буфера пришедшие данные (это я так вольно трактую п.2: "успевает принять, но не успевает обработать такой объем").
В это время "А", при использовании блокирующих сокетов, соответственно блокируется. То есть висит на операции send(). После заполнения окна TCP ждет подтверждения о доставке пакетов и ничего не отправляет. Вы это должны прекрасно понимать — именно здесь поведение может зависеть от алгоритма Нагла.
Если же "А" использует неблокирующий режим, то после заполнения внутренних буферов, соответствующие функции начнут возвращать соответствующие ошибки. Например WSASend() вернет SOCKET_ERROR, а WSAGetLastError() — WSAEWOULDBLOCK (а то и WSAENOBUFS).
Если же "успевает принять, но не успевает обработать такой объем" означает, что данные на стороне "В" из внутренних буферов TCP стека вынимаются с помощью recv() и потом скапливаются перед обработкой в какой нибудь очереди, то тут рано или поздно закончится память, выделяемая для этой очереди.
Видимо я все таки вопроса не понял — как то банально все.
Re[2]: Синхронность в TCP/IP
От: Шебеко Евгений  
Дата: 24.07.09 11:23
Оценка:
ШЕ>>Конечно странно слышать такой вопрос от человека, который около 10 лет
S>Вдвойне странен такой вопрос от человека, который в соседней ветке советует смело отключать Нагла во всех приложениях.
Ну совет базируется не на теории, а на опыте.
Не во всех. При проблеме топикстартера действительно надо отключать.
И во многих приложениях действительно приходится отключать, СУБД например.
Мне не хотелось бы спорить на эту тему в этой ветке, если вопрос будет принципиальным мне не тяжело будет написать
простой эхо сервер и наглядно показать, каким будет время отклика с TCP_NODELAY и без него.


S>Итак, у "В" не хватает ресурсов выбрать из буфера пришедшие данные (это я так вольно трактую п.2: "успевает принять, но не успевает обработать такой объем").

да, именно так.

S>В это время "А", при использовании блокирующих сокетов, соответственно блокируется. То есть висит на операции send().

S>После заполнения окна TCP ждет подтверждения о доставке пакетов и ничего не отправляет.
S>Вы это должны прекрасно понимать — именно здесь поведение может зависеть от алгоритма Нагла.

Т.е. вся синхронность базируется на ACK пакете?
Но ведь вроде на ACK есть таймаут.
И если подтверждение не приедет, TCP стек на A отправит пакет ещё раз. И так пока не решит разорвать соединение.
А если B процесс к примеру час стоять будет, то получается такая схема не работает?
Поправьте меня, если я что-то не так понимаю.
Re[3]: Синхронность в TCP/IP
От: stbzh  
Дата: 24.07.09 16:30
Оценка: 3 (1)
Здравствуйте, Шебеко Евгений, Вы писали:
ШЕ>Не во всех.
Буквально:
ШЕ>За 10 лет не помню ни одного моего приложения, где его не пришлось бы отключить.
Действительно, не было "во всех". Сорри.

По сути вопроса. Разрыв будет не сразу. Алгоритм Нагла на принимающей стороне "В" может просто немного задержать отправку АСК, чтобы дать возможность алгоритму Нагла на отправляющей стороне "А" доложить в пакет данные, отправленные вслед за первыми. Но если frame забит, то никто ничего докладывать не станет и полный пакет будет ждать подтверждения. Если АСКа долго не будет, пакет будет послан еще раз, и еще... Пока не будет достигнут максимум ретрансмиссий. А каждая ретрансмиссия будет происходить дольше предыдущей в два раза. Максимум ретрансмиссий и начальное время задержки перед ретранмиссией конфигурируются.

If a packet arrives that is larger than the available space in the stack's buffers, it may fragment a packet, queuing up as many bytes as it has buffer space for and discarding the rest. (The remote peer will resend the remaining data later.) ... If the ACK does not arrive within some particular time frame, the sending stack retransmits the packet...
TCP's "sliding window". A sliding window means that the stack can have several unacknowledged packets "in flight" before it stops and waits for the remote peer to acknowledge the first packet. When the TCP connection is established, the stacks tell each other how much buffer space they've allocated for this connection: this is the maximum window size. Since each peer knows how big the remote peer's buffer is and how many unacknowledged bytes it has sent, it will stop sending data when it calculates that the remote peer's buffer is full. Each peer then sends window size updates in each ACK packet, telling the remote peer that stack buffer space has become available...
In Microsoft Winsock stacks, the sliding window defaults to 8 KB. That means that if it sends 8 KB of data without receiving an acknowledgement for the first packet, the stack won't send any more data until the first packet is acknowledged or the retry timer goes off, at which point it will try to send the first packet again. As each packet at the front of the "window" gets acknowledged, the 8 KB window "slides" along the data stream, allowing the remote peer to send more data...
The stack is only allowed to delay ACKs for up to 2 frames of data.

Ну а насчет того, когда же это все закончится, есть например такая статья http://support.microsoft.com/kb/170359.
Приведу выдержки:

TCP starts a retransmission timer when each outbound segment is handed down to IP. If no acknowledgment has been received for the data in a given segment before the timer expires, then the segment is retransmitted, up to the TcpMaxDataRetransmissions times. The default value for this parameter is 5.
The retransmission timer is initialized to three seconds when a TCP connection is established; however, it is adjusted on the fly to match the characteristics of the connection using Smoothed Round Trip Time (SRTT) calculations as described in RFC793. The timer for a given segment is doubled after each retransmission of that segment. Using this algorithm, TCP tunes itself to the normal delay of a connection. TCP connections over high-delay links will take much longer to time out than those over low- delay links.
By default, after the retransmission timer hits 240 seconds, it uses that value for retransmission of any segment that needs to be retransmitted.
...
TcpMaxDataRetransmissions: Valid Range: 0 — 0xFFFFFFFF; Default: 5. This parameter controls the number of times TCP retransmits an individual data segment (non connect segment) before aborting the connection. The retransmission timeout is doubled with each successive retransmission on a connection. It is reset when responses resume. The base timeout value is dynamically determined by the measured round-trip time on the connection.

Re: Синхронность в TCP/IP
От: Аноним  
Дата: 24.07.09 16:48
Оценка:
ШЕ>1. A постоянно посылает большой объём данных.
ШЕ>2. B успевает принять, но не успевает обработать такой объем (к примеру записать в БД)
ШЕ>3. Что произойдёт? Процесс в A заблокируется на send() или обломится на send()?
Заблокируется при блокирубщем вызове и обломится на неблокирующем.
Если получатель будет долно не забирать данные -> долго не отсылать ack'и на готовое окно — посылатель решит (после определенного колва перепосылок) что он отвалился и порвет конекшн.
Re: Синхронность в TCP/IP
От: Vamp Россия  
Дата: 24.07.09 19:47
Оценка:
Отсюда очень простой вывод.
Данные из очереди надо выбирать как можно быстрее. Если потом с ними делается что-то принципиально медленное, то их надо складывать в другую очередь.
Да здравствует мыло душистое и веревка пушистая.
Re: Синхронность в TCP/IP
От: BigBoss  
Дата: 24.07.09 21:21
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Конечно странно слышать такой вопрос от человека, который около 10 лет

ШЕ>программирует, но увы

ШЕ>Имеем передачу данных по соединению TCP/IP от A->B.

ШЕ>Вопрос имеются ли в TCP/IP механизмы, поддерживающие синхронность передачи?

Синхронность -- это греческое слово, по-русски одновременость. Так одновременно с чем должна происходить передача?
Re[2]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.07.09 06:50
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Отсюда очень простой вывод.

V>Данные из очереди надо выбирать как можно быстрее. Если потом с ними делается что-то принципиально медленное, то их надо складывать в другую очередь.

А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.
The God is real, unless declared integer.
Re[3]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.07.09 07:26
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>>>Конечно странно слышать такой вопрос от человека, который около 10 лет

S>>Вдвойне странен такой вопрос от человека, который в соседней ветке советует смело отключать Нагла во всех приложениях.
ШЕ>Ну совет базируется не на теории, а на опыте.

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

ШЕ>Не во всех. При проблеме топикстартера действительно надо отключать.

ШЕ>И во многих приложениях действительно приходится отключать, СУБД например.
ШЕ>Мне не хотелось бы спорить на эту тему в этой ветке, если вопрос будет принципиальным мне не тяжело будет написать
ШЕ>простой эхо сервер и наглядно показать, каким будет время отклика с TCP_NODELAY и без него.

Напишите. Не думаю, что найдёте что-то противоречащее теории.

S>>В это время "А", при использовании блокирующих сокетов, соответственно блокируется. То есть висит на операции send().

S>>После заполнения окна TCP ждет подтверждения о доставке пакетов и ничего не отправляет.
S>>Вы это должны прекрасно понимать — именно здесь поведение может зависеть от алгоритма Нагла.

ШЕ>Т.е. вся синхронность базируется на ACK пакете?


Вы так и не объяснили, что такое "синхронность" в Вашем понимании. Так, как Вы её описываете, это не "синхронность", а управление потоком.

Управление потоком действительно "базируется на ACK пакете", хотя, если более точно — на ACK поле со счётчиком подтверждённой позиции. А как иначе было бы?

ШЕ>Но ведь вроде на ACK есть таймаут.

ШЕ>И если подтверждение не приедет, TCP стек на A отправит пакет ещё раз. И так пока не решит разорвать соединение.
ШЕ>А если B процесс к примеру час стоять будет, то получается такая схема не работает?

Уй, Вы натурально не понимаете. Если A отправит данные ещё раз, а B не будет иметь места в буфере их принять — B отправит ACK с той позицией, которая последняя реально принята, и с window = 0. Это будет для A означать, что B не в состоянии принять данные сейчас.

Когда же в B прикладной процесс выберет данные из буфера и в нём появится свободное место, стек на B отправит об этом сообщение с той же позицией в ACK, но ненулевым window. Это и будет сигналом для A, что можно передавать следующую порцию данных.

ШЕ>Поправьте меня, если я что-то не так понимаю.


Вы бы лучше спецификации TCP почитали. То, что я описываю, есть даже в базовом RFC793.
The God is real, unless declared integer.
Re[3]: Синхронность в TCP/IP
От: g_i  
Дата: 25.07.09 08:46
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Vamp, Вы писали:


V>>Отсюда очень простой вывод.

V>>Данные из очереди надо выбирать как можно быстрее. Если потом с ними делается что-то принципиально медленное, то их надо складывать в другую очередь.

N>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.


Чтобы освободить буфер tcp? У него м/б другие клиенты?
Как вариант, можно сообщать клиенту размер данных, который он может отправить серверу.
S -> C Send window size (n) announcement
C -> S Send data of size < n
C (sent == n) ? wait S window size announcement : Send data of size < (n — sent)
Re[4]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.07.09 09:08
Оценка:
Здравствуйте, g_i, Вы писали:

g_i>Здравствуйте, netch80, Вы писали:


N>>Здравствуйте, Vamp, Вы писали:


V>>>Отсюда очень простой вывод.

V>>>Данные из очереди надо выбирать как можно быстрее. Если потом с ними делается что-то принципиально медленное, то их надо складывать в другую очередь.

N>>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.


g_i>Чтобы освободить буфер tcp? У него м/б другие клиенты?


У буфера — нет. У сервера — да.

g_i>Как вариант, можно сообщать клиенту размер данных, который он может отправить серверу.


Не вижу практического случая, где такое лучше просто неприёма пока не обрабатывает.
The God is real, unless declared integer.
Re[3]: Синхронность в TCP/IP
От: Vamp Россия  
Дата: 27.07.09 13:26
Оценка:
N>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.
Смысл в том, что если ACK долго не придет, то клиент разорвет соединение.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Синхронность в TCP/IP
От: ДимДимыч Украина http://klug.org.ua
Дата: 27.07.09 14:54
Оценка:
Здравствуйте, Vamp, Вы писали:

N>>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.

V>Смысл в том, что если ACK долго не придет, то клиент разорвет соединение.

Почему ACK долго не придет?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[5]: Синхронность в TCP/IP
От: Vamp Россия  
Дата: 27.07.09 15:07
Оценка:
ДД>Почему ACK долго не придет?
Потому, что если приемный буфер переполнится, то принимающая сторона не будет отправлять АК.
Да здравствует мыло душистое и веревка пушистая.
Re[6]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 27.07.09 15:34
Оценка: 8 (2)
Здравствуйте, Vamp, Вы писали:

ДД>>Почему ACK долго не придет?

V>Потому, что если приемный буфер переполнится, то принимающая сторона не будет отправлять АК.

Не будет ли благородный дон любезен подсказать, с чего он это взял?
И по RFC и по практике ответный ACK передаётся.

Ниже приведен кусок расшифровки реальных переговоров, когда сервер (на 4259) не читает из сокета, а клиент упорно пытается что-то передавать.

18:29:27.383107 IP (tos 0x0, ttl 64, id 16381, offset 0, flags [DF], proto TCP (
6), length 53) 127.0.0.1.52076 > 127.0.0.1.4259: ., cksum 0x9749 (correct), 7168
1:71682(1) ack 1 win 8960 <nop,nop,timestamp 1020754716 1696086773>
0x0000: 4500 0035 3ffd 4000 4006 fcc3 7f00 0001 E..5?.@.@.......
0x0010: 7f00 0001 cb6c 10a3 a7b5 46ed 65bd 08ff .....l....F.e...
0x0020: 8010 2300 9749 0000 0101 080a 3cd7 7b1c ..#..I......<.{.
0x0030: 6518 3af5 2d e.:.-
18:29:27.383124 IP (tos 0x0, ttl 64, id 16382, offset 0, flags [DF], proto TCP (
6), length 52) 127.0.0.1.4259 > 127.0.0.1.52076: ., cksum 0x5d42 (correct), ack
71681 win 0 <nop,nop,timestamp 1696122109 1020754716>
0x0000: 4500 0034 3ffe 4000 4006 fcc3 7f00 0001 E..4?.@.@.......
0x0010: 7f00 0001 10a3 cb6c 65bd 08ff a7b5 46ed .......le.....F.
0x0020: 8010 0000 5d42 0000 0101 080a 6518 c4fd ....]B......e...
0x0030: 3cd7 7b1c <.{.
18:30:27.373975 IP (tos 0x0, ttl 64, id 20651, offset 0, flags [DF], proto TCP (
6), length 53) 127.0.0.1.52076 > 127.0.0.1.4259: ., cksum 0x22e0 (correct), 7168
1:71682(1) ack 1 win 8960 <nop,nop,timestamp 1020814716 1696122109>
0x0000: 4500 0035 50ab 4000 4006 ec15 7f00 0001 E..5P.@.@.......
0x0010: 7f00 0001 cb6c 10a3 a7b5 46ed 65bd 08ff .....l....F.e...
0x0020: 8010 2300 22e0 0000 0101 080a 3cd8 657c ..#.".......<.e|
0x0030: 6518 c4fd 2d e...-
18:30:27.373995 IP (tos 0x0, ttl 64, id 20652, offset 0, flags [DF], proto TCP (6), length 52) 127.0.0.1.4259 > 127.0.0.1.52076: ., cksum 0x8880 (correct), ack 71681 win 0 <nop,nop,timestamp 1696182109 1020814716>
0x0000: 4500 0034 50ac 4000 4006 ec15 7f00 0001 E..4P.@.@.......
0x0010: 7f00 0001 10a3 cb6c 65bd 08ff a7b5 46ed .......le.....F.
0x0020: 8010 0000 8880 0000 0101 080a 6519 af5d ............e..]
0x0030: 3cd8 657c <.e|


Хорошо сидно, что ACK отвечается немедленно, подтверждая одну из предыдущих позиций и анонсируя окно 0.
The God is real, unless declared integer.
Re[7]: Синхронность в TCP/IP
От: Vamp Россия  
Дата: 27.07.09 15:44
Оценка:
Возможно, я не прав. У меня сложилось такое впечателение.
Да здравствует мыло душистое и веревка пушистая.
Re[7]: Синхронность в TCP/IP
От: Шебеко Евгений  
Дата: 30.07.09 13:43
Оценка:
ДД>>>Почему ACK долго не придет?
V>>Потому, что если приемный буфер переполнится, то принимающая сторона не будет отправлять АК.
N>Не будет ли благородный дон любезен подсказать, с чего он это взял?
N>И по RFC и по практике ответный ACK передаётся.
N>Ниже приведен кусок расшифровки реальных переговоров, когда сервер (на 4259) не читает из сокета, а клиент упорно пытается что-то передавать.
N>Хорошо сидно, что ACK отвечается немедленно, подтверждая одну из предыдущих позиций и анонсируя окно 0.

Таки да, передаётся.
Запустил серверную часть на удалённом сервере, клиента из офисной сетки.
Чудесно сидит в блоке уже час, ничего не отваливается
При этом примерно раз в 10 сек. валит вот такая фигня.
[root@v2 /home/shebeko]# tcpdump -n port 6000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on em0, link-type EN10MB (Ethernet), capture size 96 bytes
16:31:28.047569 IP 94.154.220.69.50978 > 193.200.64.45.6000: . 1627174818:1627174819(1) ack 2403309842 win 65535 <nop,nop,timestamp 164803287 524324111>
16:31:28.047581 IP 193.200.64.45.6000 > 94.154.220.69.50978: . ack 0 win 0 <nop,nop,timestamp 524331988 164803287>
16:31:35.924698 IP 94.154.220.69.50978 > 193.200.64.45.6000: . 0:1(1) ack 1 win 65535 <nop,nop,timestamp 164811167 524331988>
16:31:35.924716 IP 193.200.64.45.6000 > 94.154.220.69.50978: . ack 0 win 0 <nop,nop,timestamp 524339865 164811167>
16:31:43.801826 IP 94.154.220.69.50978 > 193.200.64.45.6000: . 0:1(1) ack 1 win 65535 <nop,nop,timestamp 164819047 524339865>
16:31:43.801838 IP 193.200.64.45.6000 > 94.154.220.69.50978: . ack 0 win 0 <nop,nop,timestamp 524347742 164819047>
16:31:51.678956 IP 94.154.220.69.50978 > 193.200.64.45.6000: . 0:1(1) ack 1 win 65535 <nop,nop,timestamp 164826927 524347742>
16:31:51.678968 IP 193.200.64.45.6000 > 94.154.220.69.50978: . ack 0 win 0 <nop,nop,timestamp 524355620 164826927>


Ради чего я всё это спрашивал, чтобы понять можно ли от TCP потока ожидать такого же поведения, как от другого потока ОС.
Вывод можно, только это будет стоить трафика.
Эксперемент, конечно, я и сам провести мог, нужно было теоретическое подтверждение
Всем спасибо.




Тестовый клиент:
#include <iostream>
#include <string>
#include <memory>
#include <time.h>
#include "../../pubinc/sock_inet.h"
#include "../../pubinc/sock_unix.h"

using namespace SockCpp;


int main(int argc, char** argv)
{
  try
    {
        std::string host;
        if(argc>1)host=argv[1];
        
        unsigned short port=0;
        if(argc>2)port=atol(argv[2]);
        
        isocket_t* sock=0;
        
        tcp_socket_t inet_sock;
        unix_socket_t unix_sock;
        
        if(port==0)
        {
          unix_address_t addr;
            addr.init(host);
            
            unix_sock.connect(addr);
            sock=&unix_sock;
        }
        else
        {
          inet_address_t addr;
            addr.init(host,port);
            
            inet_sock.connect(addr);
            sock=&inet_sock;
        }
        
        unsigned char tmp[65536];
        unsigned data_len=0;
        
        while(true)        
        {
            unsigned ret=sock->send(tmp,sizeof(tmp));
          data_len+=ret;
        std::cout<<"ret="<<ret<<" data_len="<<data_len<<std::endl;
        }
    }
    catch(std::exception& e)
    {
      std::cout<<"std::exception: "<<e.what()<<std::endl;
    }
    catch(...)
    {
      std::cout<<"unknown exception"<<std::endl;
    }

  return 0;
}


Тестовый сервер:
#include <iostream>
#include <string>
#include <memory>
#include <time.h>
#include "../../pubinc/sock_inet.h"
#include "../../pubinc/sock_unix.h"

using namespace SockCpp;


int main(int argc, char** argv)
{
  try
    {
        std::string host;
        if(argc>1)host=argv[1];
        
        unsigned short port=0;
        if(argc>2)port=atol(argv[2]);
        
        isocket_t* listen=0;
        
        tcp_socket_t inet_sock;
        unix_socket_t unix_sock;
        
        if(port==0)
        {
          unix_address_t addr;
            addr.init(host);
            
            unlink(host.c_str());
            unix_sock.listen(addr);
            listen=&unix_sock;
        }
        else
        {
          inet_address_t addr;
            addr.init(host,port);
            
            inet_sock.listen(addr);
            listen=&inet_sock;
        }
        
        std::pair<isocket_t*,address_t*> ss=listen->accept();
        
        std::auto_ptr<isocket_t> sock(ss.first);
        std::auto_ptr<address_t> addr(ss.second);
        
        unsigned char tmp[65536];
        unsigned data_len=0;
        bool do_block=true;
        
        
        while(true)        
        {
          unsigned ret=sock->recv(tmp,sizeof(tmp));
          data_len+=ret;
        std::cout<<"ret="<<ret<<" data_len="<<data_len<<std::endl;
            if(do_block&&data_len>1000000)
            {
              std::string tt;
          std::cout<<"we block, no more read"<<std::endl;
          std::cout<<"put some and press enter to continue..."<<std::endl;
                std::cin>>tt;
                do_block=false;
            }
            
            
        }
    }
    catch(std::exception& e)
    {
      std::cout<<"std::exception: "<<e.what()<<std::endl;
    }
    catch(...)
    {
      std::cout<<"unknown exception"<<std::endl;
    }
    
  return 0;
}


Вывод с клиента:
ret=65536 data_len=65536
ret=65536 data_len=131072
ret=65536 data_len=196608
ret=65536 data_len=262144
ret=65536 data_len=327680
ret=65536 data_len=393216
ret=65536 data_len=458752
ret=65536 data_len=524288
ret=65536 data_len=589824
ret=65536 data_len=655360
ret=65536 data_len=720896
ret=65536 data_len=786432
ret=65536 data_len=851968
ret=65536 data_len=917504
ret=65536 data_len=983040
ret=65536 data_len=1048576
ret=65536 data_len=1114112


Вывод с сервера:
ret=1448 data_len=1448
ret=2896 data_len=4344
ret=1448 data_len=5792
ret=4344 data_len=10136
ret=4344 data_len=14480
Очень много лога...
ret=2896 data_len=994776
ret=4344 data_len=999120
ret=4344 data_len=1003464
we block, no more read
put some and press enter to continue...


Так это дело всё нормально стоит, столько сколько нужно.
Re[3]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 01:23
Оценка: -1
Здравствуйте, netch80, Вы писали:

N>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.


Т.е. по вашему, переложив проблемы буферизации на сетевой трафик (клиент все скидывает в сеть, а сервер упорно не вычитывает их, тем самым забивая сетевой трафик), вы решите проблему дефицитности памяти сервера/клиента? Бред! Уволил бы такого программиста без сожаления.
Re[4]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.09.09 07:37
Оценка:
Здравствуйте, Serj_K, Вы писали:

N>>А смысл? Если так делать, вы всего лишь перенесёте буферизацию на сторону сервера. Где-то это, может, и хорошо, но в большинстве случаев это просто потеря ресурсов сервера, которые более дефицитны, чем ресурсы клиента.


S_K>Т.е. по вашему, переложив проблемы буферизации на сетевой трафик (клиент все скидывает в сеть, а сервер упорно не вычитывает их, тем самым забивая сетевой трафик), вы решите проблему дефицитности памяти сервера/клиента?


Простите, что значит "забивая сетевой трафик" в данном случае? Как Вы это себе представляете? Неужели то, что передаваемые данные будут накапливаться и застревать в маршрутизаторах?;))

И почему такой подход используется во множестве промышленных решений и я не вижу про это плачей Ярославны?

S_K> Бред!


У кого? Я начинаю подозревать, что у Вас.

S_K> Уволил бы такого программиста без сожаления.


Конечно, горячее сердце — полезная для человечества штука. Но только если к нему прилагается трезвая голова. Это я пока что от Вас не увидел.
The God is real, unless declared integer.
Re[4]: Синхронность в TCP/IP
От: Шебеко Евгений  
Дата: 14.09.09 08:21
Оценка:
S_K>Т.е. по вашему, переложив проблемы буферизации на сетевой трафик (клиент все скидывает в сеть, а сервер упорно не вычитывает их,
S_K>тем самым забивая сетевой трафик), вы решите проблему дефицитности памяти сервера/клиента? Бред! Уволил бы такого программиста без сожаления.
В TCP много деталей, которые рядовому программисту ИМХО знать не обязательно.
Но вы бы хоть прочли ветку до конца здесь
Автор: netch80
Дата: 27.07.09
и здесь
Автор: Шебеко Евгений
Дата: 30.07.09
.

Вычитывать данные без необходимости, только ради того чтобы их вычитать — это зло.
Я это прочувствовал на собственных программах. Де факто процессы клиента и сервера работают с разной скоростью.
И как только клиентов становится много, а сервер нагруженным, данные с клиента начинают обрабатываться (например записываться в базу)
медленнее, чем поступают с клиентов. И ваша буферизация приведёт к тому, что сервер просто упадёт. Если вы ограничите размер буфера,
добьётесь только того, что потратите память (т.к. сервер нагружен постоянно, то и данные поступают постоянно).

У меня так и было. Я правда не старался что-то специально вычитать, просто так получилось.
Весь топик я затеял, чтобы убедится что соединение не будет разорвано если данные не вычитывать.
Как только я получил экспериментальное и теоретическое обоснование, с большим удовольствием избавился от такого поведения.
Re[5]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 10:20
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Вычитывать данные без необходимости, только ради того чтобы их вычитать — это зло.

ШЕ>Я это прочувствовал на собственных программах. Де факто процессы клиента и сервера работают с разной скоростью.
ШЕ>И как только клиентов становится много, а сервер нагруженным, данные с клиента начинают обрабатываться (например записываться в базу)
ШЕ>медленнее, чем поступают с клиентов. И ваша буферизация приведёт к тому, что сервер просто упадёт. Если вы ограничите размер буфера,
ШЕ>добьётесь только того, что потратите память (т.к. сервер нагружен постоянно, то и данные поступают постоянно).

В данном случае, если клиенту необходимо передать серверу большой объем данных, рекомендуется организовать логическую синхронизацию на прикладном уровне, так как сеть — это не "бездонная труба", и если туда кидать все данные сразу — есть большая вероятность в падении скорости из-за перегрузки трафика повторными пакетами. Т.е. по уму — клиент должен узнать у сервера, какой объем тот готов принять, а не пересылать все что у него есть. Почитай например Jon C. Snader, Effective TCP/IP Programming (Эффективное программирование TCP/IP) — там в последних главах обсуждается вопросы эффективного использования сети и проблема размера буферов.

P.S. Книгу можно достать в инете например тут: http://www.internet-technologies.ru/books/book_103.html
Re[5]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 10:33
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Serj_K, Вы писали:


N>Простите, что значит "забивая сетевой трафик" в данном случае? Как Вы это себе представляете? Неужели то, что передаваемые данные будут накапливаться и застревать в маршрутизаторах?)


N>....

Ответ здесь
Автор: Serj_K
Дата: 14.09.09
Re[6]: Синхронность в TCP/IP
От: Шебеко Евгений  
Дата: 14.09.09 10:51
Оценка:
S_K>В данном случае, если клиенту необходимо передать серверу большой объем данных, рекомендуется организовать логическую синхронизацию на прикладном уровне,
Так то оно так, но это вовсе не означает, что надо изгаляться и стремиться вычитать все данные, которые ты ещё не в состоянии обработать,
даже ещё не знаешь надо ли их вообще обрабатывать.
Клиентов тоже много может быть и небольшими пакетами от всех клиентов можно создать большой объём на сервере.

S_K>так как сеть — это не "бездонная труба", и если туда кидать все данные сразу — есть большая вероятность в падении скорости из-за перегрузки трафика повторными пакетами.

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

S_K>Т.е. по уму — клиент должен узнать у сервера, какой объем тот готов принять, а не пересылать все что у него есть.

Да не будет это работать лучше, чем работает сам TCP стек.
C1->S: А сколько я могу записать?
C2->S: А сколько я могу записать?
S->C1: 10000
S->C2: 10000
C1->S: На тебе 10000
C2->S: На тебе 10000
S: Bad alloc


S_K>Почитай например Jon C. Snader, Effective TCP/IP Programming (Эффективное программирование TCP/IP) — там в последних главах обсуждается вопросы эффективного использования сети и проблема размера буферов.

S_K>P.S. Книгу можно достать в инете например тут: http://www.internet-technologies.ru/books/book_103.html

404 (
Обложка знакомая, но что-то не могу у себя сейчас найти.
Re[6]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.09.09 11:27
Оценка:
Здравствуйте, Serj_K, Вы писали:

S_K>Здравствуйте, netch80, Вы писали:


N>>Здравствуйте, Serj_K, Вы писали:


N>>Простите, что значит "забивая сетевой трафик" в данном случае? Как Вы это себе представляете? Неужели то, что передаваемые данные будут накапливаться и застревать в маршрутизаторах?;))


N>>....

S_K>Ответ здесь
Автор: Serj_K
Дата: 14.09.09


Это не ответ, извините за откровенность. Это больше похоже на невнятное лопотание, ещё и со ссылкой на недоступные источники (Вы сами-то ссылки пробовали? они мертвы).

Я повторяю вопрос более детально. Есть протокол, в котором допускается, что клиент передаёт запросы потоком не дожидаясь ответа сервера на предыдущие запросы. Есть клиент, который передаёт таким образом и для которого заполненный до предела выходной буфер — нормальная ситуация. Что именно в данной организации неэффективно? И, чтобы не говорить голословно — ситуацию рассмотрим на примере RFC4644 и его конкретной реализации в виде innfeed. Прошу рассказать, как именно innfeed забивает сетевой трафик и кому он при этом мешает.
The God is real, unless declared integer.
Re[6]: Синхронность в TCP/IP
От: Изя Рнет Беларусь  
Дата: 14.09.09 13:00
Оценка:
Здравствуйте, Serj_K, Вы писали:

[bullshit deleted]
S_K> Т.е. по уму — клиент должен узнать у сервера, какой объем тот готов принять, а не пересылать все что у него есть.

Ви таки будете смеяться, но именно это и происходит буквально в каждом пакетном обмене в протоколе TCP. Для этого и существует поле window.
Re[7]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 15:25
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

ШЕ>Подозреваю что HTTP при скачивании больших файлов так и делает. И ничего фильмы у вас не пропадают и браузер память не выжирает

ШЕ>пока вы решаете, куда сохранить файл или просто пишите на медленную флешку.
Подозреваю, что браузер качает файл в кэш, пока вы решаете куда сохранит файл
(для IE есть такой каталог как C:\Documents and Settings\...\Local Settings\Temporary Internet Files\Content.IE5)

ШЕ>Да не будет это работать лучше, чем работает сам TCP стек.

ШЕ>
C1->>S: А сколько я могу записать?
C2->>S: А сколько я могу записать?
S->>C1: 10000
S->>C2: 10000
C1->>S: На тебе 10000
C2->>S: На тебе 10000
ШЕ>S: Bad alloc
ШЕ>

Строка C2->>S: явно лишняя... Если TCP гарантирует доставку, не вижу необходимость посылать повторный запрос...
Re[8]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.09.09 15:29
Оценка:
Здравствуйте, Serj_K, Вы писали:

S_K>Здравствуйте, Шебеко Евгений, Вы писали:


ШЕ>>Подозреваю что HTTP при скачивании больших файлов так и делает. И ничего фильмы у вас не пропадают и браузер память не выжирает

ШЕ>>пока вы решаете, куда сохранить файл или просто пишите на медленную флешку.
S_K>Подозреваю, что браузер качает файл в кэш, пока вы решаете куда сохранит файл ;)
S_K>(для IE есть такой каталог как C:\Documents and Settings\...\Local Settings\Temporary Internet Files\Content.IE5)

ШЕ>>Да не будет это работать лучше, чем работает сам TCP стек.

ШЕ>>
C1->>>S: А сколько я могу записать?
C2->>>S: А сколько я могу записать?
S->>>C1: 10000
S->>>C2: 10000
C1->>>S: На тебе 10000
C2->>>S: На тебе 10000
ШЕ>>S: Bad alloc
ШЕ>>

S_K>Строка C2->>S: явно лишняя... Если TCP гарантирует доставку, не вижу необходимость посылать повторный запрос...

Вообще-то C1 и C2 — разные клиенты одного сервера. С чего это Вы решили, что это будет "повторный запрос"?
The God is real, unless declared integer.
Re[7]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 15:31
Оценка:
Здравствуйте, Шебеко Евгений, Вы писали:

C1->>S: А сколько я могу записать?

C2->>S: А сколько я могу записать?
S->>C1: 10000
S->>C2: 10000
C1->>S: На тебе 10000
C2->>S: На тебе 10000
ШЕ>S: Bad alloc
ШЕ>[/code]

Сорри, я не разобрал семантики...
В таком, случае строка S->>C2: 10000 лишняя. Т.е. если сервер предоставил 1-у клиенту память — то следует залочить эту память во избежание вышеописанной ситуации. Это мое мнение.
Re[7]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 15:52
Оценка:
Здравствуйте, netch80, Вы писали:

N>Это не ответ, извините за откровенность. Это больше похоже на невнятное лопотание, ещё и со ссылкой на недоступные источники (Вы сами-то ссылки пробовали? они мертвы).

Пробовал — работает. Там между прочим есть название книги, если что. Было-бы желание — найти ее в инете не составит труда...

N>Я повторяю вопрос более детально. Есть протокол, в котором допускается, что клиент передаёт запросы потоком не дожидаясь ответа сервера на предыдущие запросы. Есть клиент, который передаёт таким образом и для которого заполненный до предела выходной буфер — нормальная ситуация. Что именно в данной организации неэффективно? И, чтобы не говорить голословно — ситуацию рассмотрим на примере RFC4644 и его конкретной реализации в виде innfeed. Прошу рассказать, как именно innfeed забивает сетевой трафик и кому он при этом мешает.

Извини — я не знаю что за innfeed и как он работает, так что ничего не смогу тебе ответить...
Re[8]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.09.09 17:18
Оценка: +1
Здравствуйте, Serj_K, Вы писали:

N>>Это не ответ, извините за откровенность. Это больше похоже на невнятное лопотание, ещё и со ссылкой на недоступные источники (Вы сами-то ссылки пробовали? они мертвы).

S_K>Пробовал — работает. Там между прочим есть название книги, если что. Было-бы желание — найти ее в инете не составит труда...

Я пока не понял, зачем мне стараться её искать.

N>>Я повторяю вопрос более детально. Есть протокол, в котором допускается, что клиент передаёт запросы потоком не дожидаясь ответа сервера на предыдущие запросы. Есть клиент, который передаёт таким образом и для которого заполненный до предела выходной буфер — нормальная ситуация. Что именно в данной организации неэффективно? И, чтобы не говорить голословно — ситуацию рассмотрим на примере RFC4644 и его конкретной реализации в виде innfeed. Прошу рассказать, как именно innfeed забивает сетевой трафик и кому он при этом мешает.

S_K>Извини — я не знаю что за innfeed и как он работает, так что ничего не смогу тебе ответить...

Информацию об этом найти значительно проще, чем книгу. А прочитать RFC на десяток страниц — тем более. Так что ничего кроме "слив защитан" тут, увы, сказать не получается. Хорошо начинаете жизнь в форуме, коллега. Так держать.
The God is real, unless declared integer.
Re[9]: Синхронность в TCP/IP
От: Serj_K  
Дата: 14.09.09 19:34
Оценка:
Здравствуйте, netch80, Вы писали:

N>Я повторяю вопрос более детально. Есть протокол, в котором допускается, что клиент передаёт запросы потоком не дожидаясь ответа сервера на предыдущие запросы. Есть клиент, который передаёт таким образом и для которого заполненный до предела выходной буфер — нормальная ситуация. Что именно в данной организации неэффективно? И, чтобы не говорить голословно — ситуацию рассмотрим на примере RFC4644 и его конкретной реализации в виде innfeed. Прошу рассказать, как именно innfeed забивает сетевой трафик и кому он при этом мешает.


N>Информацию об этом найти значительно проще, чем книгу. А прочитать RFC на десяток страниц — тем более. Так что ничего кроме "слив защитан" тут, увы, сказать не получается. Хорошо начинаете жизнь в форуме, коллега. Так держать.


Хорошо, не будешь столь любезен выложить исходный код этого innfeed'а, а то мне, так-же как и тебе — лень искать книгу, лень копаться в документации. A я просмотрю его и расскажу свое мнение — забивает innfeed или нет сетевой трафик, как и почему...

А по описанному топикстартером примеру — давай разберемся сначала, перед тем как критиковать. Итак по моему разумению, при выключается алгоритм Нагла (который как раз и следит, чтоб мелкие пакеты не перегружали сеть) и при интенсивной отправке данных — TCP буфер сервера перегружается, так как он их не вычитывает. Пакеты после переполнения буфера на сервере остаются в сети и уничтожаются после завершения их времени жизни TTL. Поэтому, клиентская сторона отсылает их заново, и т.д. и т.д. Это разве не забивание трафика лишними пакетами, вместо того чтоб спокойно подождать, пока освободятся ресурсы сервера?
Если что-то не так — поправь меня.

Тем более логику алгоритма отправки данных можно построить таким образом, чтоб TCP буфер сервера не освобождался более чем, скажем на 50%, и тем самым исключить простаивание сервера, в ожидании следующего блока данных от клиента. А сеть в данном контексте является самым узким местом при передачи данных от клиента серверу — а следовательно самым дефицитным ресурсом. Поэтому его, по моему мнению, необходимо экономить в первую очередь.
Re[10]: Синхронность в TCP/IP
От: Cyberax Марс  
Дата: 14.09.09 19:46
Оценка:
Здравствуйте, Serj_K, Вы писали:

S_K>Хорошо, не будешь столь любезен выложить исходный код этого innfeed'а, а то мне, так-же как и тебе — лень искать книгу, лень копаться в документации. A я просмотрю его и расскажу свое мнение — забивает innfeed или нет сетевой трафик, как и почему...

http://packages.debian.org/source/sid/innfeed

S_K>А по описанному топикстартером примеру — давай разберемся сначала, перед тем как критиковать. Итак по моему разумению, при выключается алгоритм Нагла (который как раз и следит, чтоб мелкие пакеты не перегружали сеть) и при интенсивной отправке данных — TCP буфер сервера перегружается, так как он их не вычитывает. Пакеты после переполнения буфера на сервере остаются в сети и уничтожаются после завершения их времени жизни TTL.

Бред. TTL — это максимальное количество хопов. После того, как пакет дошёл до назначения оно уже ни на что не влияет.

В общем, почитай что-нибудь по теории сетей, и устройству TCP/IP. Так как сплошной бред несёшь.
Sapienti sat!
Re[10]: Синхронность в TCP/IP
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.09.09 21:05
Оценка:
Здравствуйте, Serj_K, Вы писали:

S_K>Хорошо, не будешь столь любезен выложить исходный код этого innfeed'а,


ftp://ftp.isc.org/isc/inn/inn-2.5.0.tar.gz

делать своё локальное зеркало не вижу смысла:)

S_K> а то мне, так-же как и тебе — лень искать книгу, лень копаться в документации. A я просмотрю его и расскажу свое мнение — забивает innfeed или нет сетевой трафик, как и почему...


ню ню:))

S_K>А по описанному топикстартером примеру — давай разберемся сначала, перед тем как критиковать. Итак по моему разумению, при выключается алгоритм Нагла (который как раз и следит, чтоб мелкие пакеты не перегружали сеть) и при интенсивной отправке данных — TCP буфер сервера перегружается, так как он их не вычитывает.


Нет.

S_K> Пакеты после переполнения буфера на сервере остаются в сети и уничтожаются после завершения их времени жизни TTL.


О боже. Пакеты остаются в сети. Это покруче славянских корней египтян.

S_K>Если что-то не так — поправь меня.


Правлю. Всё не так. В школу, учиться читать.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.