Ограничение Windows на количество одновременно открытых сокетов / соединений на машине

Допустим, у меня есть Windows 7 с одним реальным сетевым интерфейсом и несколькими интерфейсами обратной связи. У меня есть сервер с поддержкой IOCP, который принимает соединения от клиентов. Я пытаюсь имитировать как можно больше реальных клиентских подключений к серверу.

Мой клиентский код просто устанавливает X количество подключений сокетов (обратите внимание, что клиент привязывается к заданному интерфейсу):

        const Int32 remotePort = 12345;
        const Int32 MaxSockets = 60000;

        Socket[] s = new Socket[MaxSockets];
        IPEndPoint bindEndpoint = new IPEndPoint(IPAddress.Parse(args[0]), 0);
        for (Int32 i = 0; i < MaxSockets; i++)
        {
            s[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s[i].SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            s[i].Bind(bindEndpoint);
            s[i].Connect(args[1], remotePort);

            IPEndPoint socketInfo = (IPEndPoint)s[i].LocalEndPoint;
            Console.WriteLine(String.Format("Connected socket {0} {1} : {2}", i, socketInfo.Address, socketInfo.Port));
        }

В интерфейсе обратной связи у меня есть несколько IP-адресов, которые я использую для привязки. Кроме того, я также использую настоящий интерфейс для привязки. Я столкнулся с проблемой, когда количество открытых сокетов составляет около 64 КБ на машину:

Необработанное исключение: System.Net.Sockets.SocketException: операция с сокетом не может быть выполнена из-за недостатка в системе достаточного буферного пространства или из-за переполнения очереди

Я пробовал несколько беспомощных вещей, таких как: - установка MaxUserPort на максимальное значение и некоторые другие рекомендуемые параметры TCPIP в реестре. - попытка запустить два сервера на разных интерфейсах (реальные интерфейсы и loopback) и использовать несколько клиентов.

Это известное ограничение в Windows или его можно как-то преодолеть?

Спасибо за помощь!


person a_m    schedule 28.02.2012    source источник
comment
Проверьте этот ответ   -  person tenorsax    schedule 28.02.2012
comment
Спасибо, я прочитал эту ветку, но она не отвечает на вопрос. Я пробовал то, что сделал CharlesO, но на самом деле это не сработало.   -  person a_m    schedule 28.02.2012
comment
обратите внимание, что клиент привязывается к заданному интерфейсу. Почему?   -  person user207421    schedule 29.02.2012
comment
В основном из-за ограничения TCP / IP по количеству портов на один IP-адрес. Итак, я хотел, например, 64 КБ открытых портов на interface1 и 64 КБ открытых портов на interface2, и так далее. Но общее / общее количество портов, которые я могу привязать ко всем интерфейсам в системе, по-прежнему составляет около 64 КБ. Например. вот сообщение: stackoverflow.com/a/634547/1238124   -  person a_m    schedule 29.02.2012


Ответы (4)


Я нашел на какой-то странице Microsoft, что:

... HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort Подраздел реестра определяется как максимальный порт, до которого порты могут быть выделены для привязок с подстановочными знаками. Значение записи реестра MaxUserPort определяет динамический диапазон портов ...

Итак, если я заставляю конечную точку использовать определенный порт, например

IPEndPoint bindEndpoint = new IPEndPoint(IPAddress.Parse(args[0]), 54321);

Тогда я могу открыть в системе более 64К одновременных сокетов.

person a_m    schedule 29.02.2012

В вашем примере кода вы вызываете Bind(bindEndpoint), но не показываете, как определяется bindEndpoint. Проверь это :

  • На самом деле ваша система имеет несколько IP-адресов (петля не учитывается)
  • Фактически вы устанавливаете IP-адрес конечной точки на IP-адрес (не loopback)
  • Привязки распространяются по нескольким IP-адресам.

Адрес обратной связи не учитывается, поскольку многие системы обрабатывают его специально для целей маршрутизации и привязки. Таким образом, привязка к портам в обратной петле может поглощать порты по всем адресам так же, как если бы вы были привязаны к INADDR_ANY (0.0.0.0).

person Seth Noble    schedule 29.02.2012
comment
Я разместил полный код сейчас. Как я объяснил, даже если я привязываюсь к разным интерфейсам (реальный и loopback, или только loopback): server1 и client1 на interface1, server2 и client2 на interface2 и т. Д., Максимальное количество открытых сокетов на систему составляет около 64 КБ. - person a_m; 29.02.2012

И TCP, и UDP используют 16-разрядное целое число без знака для обозначения номера порта. Я не думаю, что какая-либо реализация в какой-либо операционной системе сможет в лучшем случае открывать более 65535 сокетов на каждый связанный адрес. Кроме того, я не удивлюсь, если Windows не реализует полностью изолированные таблицы состояний для каждого адаптера или каждого привязанного адреса, а вместо этого полагается на глобальную таблицу состояний. Если это так, то это будет ограничение сетевой архитектуры Windows, а не мягкое настраиваемое ограничение.

person Geoff    schedule 28.06.2016

Я разработал инструмент для нагрузочного тестирования.

Работая на Windows 10 / 16G RAM, он мог успешно установить 60 000 соединений с сервером.

Но при попытке создать больше подключений инструмент скоро сообщит сокет WinError 10055 No Buffer Space Available.

Согласно этой статье, я думаю, что ограничение - это общий размер буфера сокета всей ОС, а не количество открытых файлов.

person Jcyrss    schedule 07.07.2020