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

Исходное сообщение
"несколько вопросов по TCP/UDP"

Отправлено pupkin , 22-Окт-11 11:36 
Подскажите по нескольким вопросам.
1. К примеру сервер висящий на accept`е принимает запросы на подключение от юзеров. Для каждого принятого соединения ОС выделяет порт на том же IP к которому привязан слушающий сокет? Таким образом для одного IP может быть принято(в идеале) 65к соединений?

2. Возможно ли на одной сетевухе принять/создать более 65к соединений? Если да - ткните плиз в ссылку где конкретно объясняется метода.

3. UDP протокол не гарантирует доставку, это всем известно. Но может ли случится так, что некоторый пакет придет частично?

4. Флаги для сокетов SO_RCVBUF и SO_SNDBUF get/set размер соответствующих буферов. Скажите, исходя из чего, и руководствуюсь какими принципами/основами/критериями рассчитывается размер буферов.


всем сильно благодарен.


Содержание

Сообщения в этом обсуждении
"несколько вопросов по TCP/UDP"
Отправлено BillyBoy , 23-Окт-11 03:34 
1. да
2. Hint: на сетевухе может быть много IP адресов
3. Нет (частичный=некорректный. пакет просто дропнется)


"несколько вопросов по TCP/UDP"
Отправлено Andrey , 24-Окт-11 14:06 
1. На сервере на одном IP на одном порту может быть множество  одновременных соединений, а не одно. В каждом соединении свой ip/порт клиента

"несколько вопросов по TCP/UDP"
Отправлено вордфильтрподавись , 28-Окт-11 00:28 
> 1. да

Нет. В случае tcp/ip соединение - двусторонний туннель между endpoint'ами заданными парами ip:port:

src_ip:src_port <-> dst_ip:dst_port.

Итого 4 числа. Для однозначной идентификации туннеля, очевидно, хоть 1 из этих 4 чисел у разных туннелей должно отличаться.

Для исходящего соединения src_ip - айпи машины-клиента которая инициирует соединение (для multihome машин у которых их несколько в принципе можно явно ткнуть какой из айпи юзать), порт src_port как правило автоматически назначается ОС, хотя при наличии особых соображений можно его задать явно. Обычно ОСи назначают порты старше 1024, инкрментя на 1 по мере надобности. Очень характерно выглядит в netstat. Ну а сервер слушает на одном(а может и нескольких, если multihomed) dst_ip, и на одном конкретном dst_port.

Что отсюда следует? Клиент не может инициировать к серверу более чем 65к соединений(на 1 имеющийся айпи ифейса), иначе утратит возможность различать туннели между собой.Потому что со стороны сервера 2 числа не меняются, а со стороны клиента портов 65К ну и 1 или несколько ip.

С другой стороны, серверу ничто не мешает принимать до 65К соединений одновременно с каждого клиента: он ловит все пакеты на 1 входной порт, а вот у разных клиентов же еще и ip разный! Меняются src_ip и src_port, 2 числа для уникальной идентификации туннеля. В случае ipv4 сервер в теории мог бы принять почти (2^32) * (2^16) т.е. примерно 2^48 соединений. Реально разумеется ресурсы у сервера закончатся раньше. Поскольку хоть на входящее соединение и не выделяется новый порт, зато как минимум отслеживать состояние соединения-надо.

В случае udp - вообще нет понятия "соединение". Поэтому и такого понятия как "65к соединений" там тоже нет.

> 2. Hint: на сетевухе может быть много IP адресов

Только вот у сервера и с одним никаких проблем не будет: айпишник у клиентов то меняется, что тоже позволяет отличать туннели. Клиент не может реюзать порты на выход как раз потому что при этом все 4 числа были бы одинаковы, не давая возможности отличать туннели друг от друга(айпи сервера и клиента не меняются, порт сервера тоже, вот и остается менять исходящий порт клиента при открытии еще 1 соединения к тому же хосту, т.к. это единственное что получается менять). Но у сервера этой проблемы нет. Потому что он может различать туннели по айпи клиента и порту.

> 3. Нет (частичный=некорректный. пакет просто дропнется)

4. Буфера рассчитываются исходя из желаемой скорости и латентности. Чем выше желаемая скорость передачи данных и латентность сети и/или обслуживания сокетов, тем жирнее надо буфер чтобы удержать в нем то что навалилось за это время. Вообще, однозначно определить оптимальный размер буфера нетривиально. Для 10 Гбит эзернета между соседними машинами оптимальный буфер будет немного иной чем для тощего adsl с 128 кбит аплоада. А какой линк подсунут - заранее неизвестно.А, ну и операционка имеет свое мнение о том сколько еще можно вам дать, а сколько уже больно жирно(для некоторых типов соединений этот параметр ОС еще и тюнят для макс. производительности).


"несколько вопросов по TCP/UDP"
Отправлено BillyBoy , 29-Окт-11 17:44 
Таким образом для одного IP может быть принято(в идеале) 65к соединений?
>> 1. да
> Нет. В случае tcp/ip соединение - двусторонний туннель между endpoint'ами заданными парами
> ip:port:
> Что отсюда следует? Клиент не может инициировать к серверу более чем 65к
> соединений

Вы сами себе противоречите, любезный.


"несколько вопросов по TCP/UDP"
Отправлено Аноним , 04-Ноя-11 18:46 
> Таким образом для одного IP может быть принято(в идеале) 65к соединений?

Да, на 1 порт 1 айпишника какой-то машины с вашей стороны не может быть более 65К соединений. Потом у вас кончатся порты назначаемые на вашу сторону исходящего соединения и не получится создавать соединения которые чем-то отличаются от предыдущих.

>> Что отсюда следует? Клиент не может инициировать к серверу более чем 65к соединений
> Вы сами себе противоречите, любезный.

Wrong: вы забываете что сервер может обслуживать более 1 клиента. Айпи клиентов будет разный, поэтому соединений принятых сервером может быть и более 65К. Например, если клиентов 10, с 10 разных айпи в теории на сервер может прийти до 650К уникально идентифицируемых соединений.


"несколько вопросов по TCP/UDP"
Отправлено pavlinux , 08-Ноя-11 01:56 
>> Таким образом для одного IP может быть принято(в идеале) 65к соединений?
> Да, на 1 порт 1 айпишника какой-то машины с вашей стороны не может быть более 65К соединений.

Да ну!? А если 1000500 виртуалок + 1000000 LXC контейнеров + вы ещё и NATом работаете.

---

Короче, pupkin, забей на теорию. Бабло решает все проблемы.


"несколько вопросов по TCP/UDP"
Отправлено pavlinux , 30-Окт-11 05:47 
> Подскажите по нескольким вопросам.
> 1. К примеру сервер висящий на accept`е

Сервер не висит на accept()!!!

> принимает запросы на подключение от
> юзеров. Для каждого принятого соединения ОС выделяет порт на том же
> IP к которому привязан слушающий сокет? Таким образом для одного IP
> может быть принято(в идеале) 65к соединений?

4294967295

> 2. Возможно ли на одной сетевухе принять/создать более 65к соединений?
> Если да - ткните плиз в ссылку где конкретно объясняется метода.


/*
* Maximum number of SYN_RECV sockets in queue per LISTEN socket.
* One SYN_RECV socket costs about 80bytes on a 32bit machine.
* It would be better to replace it with a global counter for all sockets
* but then some measure against one socket starving all other sockets
* would be needed.
*
* It was 128 by default. Experiments with real servers show, that
* it is absolutely not enough even at 100conn/sec. 256 cures most
* of problems. This value is adjusted to 128 for very small machines
* (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
* Note : Dont forget somaxconn that may limit backlog too.
*/


Documentation/networking/ip-sysctl.txt


somaxconn - INTEGER
        Limit of socket listen() backlog, known in userspace as SOMAXCONN.
        Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
        for TCP sockets.

> 3. UDP протокол не гарантирует доставку, это всем известно. Но может ли
> случится так, что некоторый пакет придет частично?

Прибьёт и попросит повтор.

> исходя из чего, и руководствуюсь какими принципами/основами/критериями рассчитывается
> размер буферов.


        case SO_SNDBUF:
                /* Don't error on this BSD doesn't and if you think
                   about it this is right. Otherwise apps have to
                   play 'guess the biggest size' games. RCVBUF/SNDBUF
                   are treated in BSD as hints */


                if (val > sysctl_wmem_max)
                        val = sysctl_wmem_max;
set_sndbuf:
                sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                if ((val * 2) < SOCK_MIN_SNDBUF)
                        sk->sk_sndbuf = SOCK_MIN_SNDBUF;
                else
                        sk->sk_sndbuf = val * 2;

                /*
                 *      Wake up sending tasks if we
                 *      upped the value.
                 */
                sk->sk_write_space(sk);


> всем сильно благодарен.