Можно и на одном IP. Если ты слушаешь сокет и к тебе подсоединилось 100000 клиентов, с твой стороны это 100000 сокетов не только на одном IP но и на одном порту.
Ещё раз повторяю: количество сокетов ограничено только ресурсами системы и никак не связано с ограничением количества портов. На сервере используется _один_ порт, поэтому его эта проблема не касается и на нём будет создаваться столько сокетов, сколько хватит памяти. На клиентах, понятное дело, нужно тюнить диапазоны портов и/или использовать разные адреса.
как вообще может быть на одной машине больше 65536 открытых сокетов?
порты никакого отношения к сокетам не имеют. Разве что слушать ты можешь не больше 65536 сокетов, ибо если один порт слушать двумя сокетами(сразу), получится ерунда.
положим есть сервер и есть миллион клиентов, каждый клиент ломится на один и тот же ip сервера, на один и тот же порт и устанавливает одно соединение. Но сервер когда делать accept() порождает новый сокет на каждое новое соединение, так вот упирается сервер в потолок. sysctl net.ipv4.ip_local_port_range помогает поднять потолок выше. но все одно это не миллион соединений. как сделать миллион на одном IP:PORT?
память свободная есть, ulimit поднят на файлы и память.
Но сервер когда делать accept() порождает новый сокет на каждое новое соединение, так вот упирается сервер в потолок. sysctl net.ipv4.ip_local_port_range помогает поднять потолок выше
подправьте ip/port, сделайте ulimit -n 1000000, запустите server и натравите на него один или несколько client с одной или нескольких машин и добейтесь миллиона открытых соединений на сервере...
Выставляем /proc/sys/fs/file-max, потом ulimit -Hn с ulimit -Sn, в сервере привязываем по INADDR_ANY и тогда даже с одной машины клиентами можно подключаться по любым адресам интерфейсов (то есть по 127.*.*.* при маске 255.0.0.0 на lo, по любым его aliasам (lo:1, lo:2, ... с соответствующими IP) и т.д. для других интерфейсов) — каждый клиент количество портов исчерпывает, но на сервере соединений может быть сколько угодно (можно /proc/sys/net/ipv4/ip_local_port_range сделать совсем небольшим — не важно).
Вообще соединение это (адрес1, порт1, адрес2, порт2) — сервер берёт адрес1 и порт1, в простом случае клиенты на той же машине берут тот же адрес2 и исчерпывают порты в порт2, так что может показаться то что тебе кажется, но на самом деле ведь есть ещё адрес2 — локально его можно варьировать (как с INADDR_ANY), ну а нормально при разных машинах он будет и так разным.
пойми простой момент, для идентификации соединения используется не пара IP:PORT, а четвёрка LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT
поэтому для одного ip и одного порта ты можешь открыть сколько угодно соединений от разных клиентов, хоть миллион (хотя наверное конечно есть какое то ограничение, может там я не знаю int 32-разрядный или ещё что.. но это точно не 65к, а сильно больше).
То есть адрес сервера при INADDR_ANY может варьироваться. А адрес клиента можно прямо с помощью bind присваивать если на интерфейсе(ах) есть что. Например: