2009-05-25 17 views
6

Sto scrivendo un piccolo server Comet in C#, e per testarlo ho scritto un piccolo programma che apre un po 'di connessioni, scrive un piccolo testo per ognuna di esse e poi chiude ciascuna di loro:Creazione di 100.000 connessioni 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); 
} 

sto usando Windows XP in questo momento, che assegna solo porte client dinamici dal 1025-5000 gamma, così ho aggiunto esplicito legame con le porte a partire da 30000. Questo mi ha portato da sotto 4000 connessioni a poco più di 16000, ma ora sto ottenendo la seguente eccezione su Socket.Connect:

"Un'operazione su una presa non potrebbe essere eseguito perché il sistema non disponeva di spazio sufficiente del buffer o perché una coda era piena 127.0.0.1:1999 "

Qualche idea? La modifica della dimensione del buffer di invio e ricezione non sembra fare alcuna differenza e sembra sempre essere la mia app client che si interrompe, mai il mio server. Mi rendo conto che finirò per esaurire le porte dei client prima di arrivare a 100.000 connessioni, ma mi piacerebbe comunque capire cosa sta succedendo un po 'meglio.

risposta

1

Windows XP (e altre versioni presumibilmente) hanno limiti sul numero di porte aperte consentite in qualsiasi momento. Questo MSDN articl e potrebbe essere utile per modificare i parametri TcpIp per aumentare il numero di porte disponibili e ridurre il tempo di attesa della porta prima che sia possibile riutilizzarlo.

+0

Penso di aver già esaurito le risorse di esaurimento del porto. Il binding esplicito è lì per gestire il numero limitato di porte assegnate dinamicamente e Socket.Disconnect libera il socket un po 'più veloce di un Socket.Close, quindi posso rieseguire il test senza attendere l'intervallo TIME_WAIT. – Daryl

+0

Penso che ci sia anche un parametro limite di velocità, ma per questo non ho trovato un riferimento MSDN. L'altro sospetto che ho è il numero di buffer di rete disponibili. – tvanfosson

+0

Non è necessario il binding esplicito per gestire il limite dinamico, è sufficiente regolare il limite come suggerito da tvanfosson. –

3

È possibile che si stia esaurendo la memoria non di paging. Ci sono limiti per macchina e per processo che sono basati sulla quantità di RAM installata, OS, impostazioni dello switch da 3 GB, ecc. Gli OS OS a 32 bit 'hanno un limite molto inferiore sulla memoria non paginata rispetto agli sku OS a 64 bit.

+0

Sembrava promettente, ma quando il mio client di test muore, sto usando meno di 28 MB di memoria del kernel non pagata. Da quello che ho letto, il limite a livello di sistema dovrebbe essere almeno 100 MB. Sembra che non stia nemmeno raggiungendo il limite per processo, perché quando il client muore utilizza meno di 8 MB, mentre il server sembra funzionare bene a oltre 10 MB. – Daryl

3

Penso che 100.000 connessioni non siano un obiettivo possibile.

Le porte TCP/IP sono numeri a 16 bit. Quindi qualsiasi cosa sopra 65535 è un no-go comunque.

+0

Sì, nella descrizione dico che finirò le porte client prima che arrivi a 100.000, ma mi piacerebbe provare a raggiungere qualche limite così difficile prima di arrendermi. – Daryl

+0

Ci ho pensato un po 'di più. Le porte TCP/IP sono effettivamente indirizzate da ip e port, quindi posso usare ogni porta una volta per ciascun indirizzo IP. Connessione a un servizio locale Posso usare l'indirizzo locale (127.0.0.1) e l'indirizzo esterno predefinito, che mi dà più di 100.000 endpoint client diversi. Ho provato questo e funziona bene sul mio Windows XP box. – Daryl

+1

ancora, se ci si connette ad alcuni ip/port esterni o interni, ha ancora bisogno di una combinazione ip/port locale. ad es. Dico che mi collego a google.com:80 quindi viene assegnata anche una porta locale. Sono le combo di localport in cui finisci. Quindi non capisco come si possa andare oltre il limite di 65536. – Toad

Problemi correlati