2009-05-25 9 views
6

Escribo un pequeño servidor Comet en C#, y para probarlo he escrito un pequeño programa que abre un grupo de conexiones, escribe un pequeño texto para cada una de ellas, y luego cierra cada una de ellos:Creando conexiones de 100,000 tcp usando .NET

int basePort = 30000; 
IPAddress localAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); 
List<Socket> sockets = new List<Socket>(); 

for(int i = 0; i < 20000; i++) { 
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    s.Bind(new IPEndPoint(localAddress, basePort + i)); 
    s.Connect("localhost", 1999); 
    sockets.Add(s); 
} 

string message = "hello"; 
byte[] messageData = Encoding.ASCII.GetBytes(message); 
foreach(Socket s in sockets) { 
    s.Send(messageData); 
} 

foreach(Socket s in sockets) { 
    s.Disconnect(false); 
} 

estoy utilizando Windows XP en este momento, que sólo se asigna puertos de cliente dinámicas de la gama de 1025 a 5000, por lo que he añadido explícita unión a los puertos a partir de 30000. Esto me tomó de debajo de 4000 conexiones a un poco más de 16000, pero ahora obtengo la siguiente excepción en Socket.Connect:

"No se pudo realizar una operación en un socket se realizó porque el sistema carecía de espacio suficiente en el búfer o porque una cola estaba llena 127.0.0.1:1999 "

¿Alguna idea? Cambiar el tamaño del búfer de envío y recepción no parece hacer ninguna diferencia, y siempre parece ser la aplicación de mi cliente la que se rompe, nunca mi servidor. Me doy cuenta de que me voy a quedar sin puertos cliente antes de llegar a las 100.000 conexiones, pero aún me gustaría entender qué está pasando un poco mejor.

Respuesta

1

Windows XP (y otras versiones, presumiblemente) tienen límites en la cantidad de puertos abiertos permitidos en cualquier momento. Esto MSDN articl e puede ser útil al modificar los parámetros TcpIp para aumentar el número de puertos disponibles y disminuir la cantidad de tiempo que Windows mantiene abierto el puerto antes de poder reutilizarlo.

+0

Creo que ya tengo solucionado el problema del agotamiento del puerto. El enlace explícito está ahí para tratar con la cantidad limitada de puertos asignados dinámicamente, y Socket.Disconnect libera el socket un poco más rápido que un Socket.Close, por lo que puedo volver a ejecutar mi prueba sin esperar el intervalo TIME_WAIT. – Daryl

+0

Creo que también hay un parámetro de límite de velocidad, pero no encontré una referencia de MSDN para eso. La otra sospecha que tengo es la cantidad de almacenamientos intermedios de red disponibles. – tvanfosson

+0

No necesita un enlace explícito para lidiar con el límite dinámico, solo necesita ajustar el límite como lo sugirió tvanfosson. –

3

Es posible que se esté quedando sin memoria no paginada. Hay límites por máquina y por proceso que se basan en la cantidad de ajustes instalados de RAM, OS,/3GB, etc. Los skus OS de 32 bits tienen un límite mucho más bajo en la memoria no paginada que los sku del SO de 64 bits.

+0

Eso parecía prometedor, pero cuando mi cliente de prueba muere, estoy usando menos de 28 MB de memoria del kernel no paginado. Por lo que he leído, el límite de todo el sistema debería ser de al menos 100 MB. Parece que tampoco estoy llegando al límite por proceso, porque cuando el cliente muere usa menos de 8MB, mientras que el servidor parece estar funcionando bien a más de 10MB. – Daryl

3

Creo que 100.000 conexiones no es un objetivo factible.

Los puertos TCP/IP son números de 16 bits. Entonces, cualquier cosa por encima de 65535 es un no ir de todos modos.

+0

Sí, en la descripción menciono que me quedaré sin puertos cliente antes de llegar a 100.000, pero me gustaría tratar de llegar a un límite difícil como ese antes de darme por vencido. – Daryl

+0

He pensado un poco más sobre esto. Los puertos TCP/IP se abordan en realidad por IP y puerto, por lo que puedo usar cada puerto una vez para cada dirección IP. Al conectarme a un servicio local, puedo usar la dirección local (127.0.0.1) y la dirección externa predeterminada, que me da más de 100.000 puntos finales de clientes diferentes. He probado esto y funciona muy bien en mi caja de Windows XP. – Daryl

+1

todavía, si se conecta a algún puerto/IP externo o interno, también necesita una combinación local de puerto/IP. p. digamos que me conecto a google.com:80 y luego se asigna un puerto local también. Son los combos de puertos locales donde te quedas sin él. Así que no entiendo cómo se puede ir por encima del límite 65536. – Toad

Cuestiones relacionadas