c - Bedste tilgang til ikke-blokerende server/lytte socket i en multi-thread applikation på Windows?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver en TCP-server/klientprogram på Windows for at blive fortrolig med Winsock API. Jeg kommer fra en UNIX-baggrund og vil gerne vide, hvilken af ​​disse kan være den bedste metode til at implementere applikationen:


Først specifikationen



  • Skal skaleres på multiprocessor- og enkeltprocessorsystemer.

  • Ingen hardset grænse for forbindelser.

  • Programmet kan både lytte til forbindelser, fungere som server og fungere som klient.

  • Multi threaded.



Første tilgang :



  • Ikke-blokerende selektivt stik til lytter, i 'server' -tråden.

  • For hver klient, der forbinder, henter vi en separat tråd.



Anden tilgang :



  • Blokerer stikkontakten til lytning, i 'server' -tråden.

  • For hver klient, der forbinder, henter vi en separat tråd.



Tredje tilgang :



  • Ikke-blokerende selektivt stik til lytter, i 'server' -tråden.

  • Ingen særskilt tråd for hver indgående forbindelse, protokollen vil have brug for statslige oplysninger, der holdes på tværs af sessioner, som jeg formoder.



Jeg spekulerer på, hvad der er den mest effektive og skalerbare tilgang, og især hvis det også kan fungere med en UDP-stikkontakt.


Bemærk: Jeg skriver ansøgningen i almindelig og gammel C. Nej. NET eller C ++ involveret, C ++ undtagelser også deaktiveret.

Bedste reference


Som Gary siger, er I/O-kompletteringsporte den mest effektive måde at styre flere netværksforbindelser på en ikke-blokkerende/asynk måde på Windows-platforme.


Med IOCP får du besked, når dine netværksoperationer er færdige, og du kan behandle disse udførelser med et lille antal tråde. Du bestemmer, hvor mange tråde du tildeler for at behandle udførelserne, og kernen bestemmer, hvornår du bruger de tråde, du leverer. Den bruger dem i en LIFO-ordre for at reducere kontekstskift, så hvis du kun bruger den minimale antal tråde, der kræves på et hvilket som helst tidspunkt, og du genbruger de samme tråde i stedet for at cykle gennem alle de tråde, du har til rådighed til brug.


Den asynkrone karakter af IOCP programmering kan være lidt forvirrende til at begynde med, men når du kommer på hænge af det, er det ret lige fremad.


Jeg har nogle gratis IOCP-serverkode, der viser det grundlæggende og giver nogle eksempel servere, der er ret nemme at bygge videre på. Du kan finde koden her: http://www.serverframework.com/products---the-free-framework.html. Den side linker også til nogle artikler, som jeg skrev for at forklare koden. [2]


Vedrørende dette til detaljerne i dit spørgsmål. Du bør se på en variation på din tredje tilgang. Brug AcceptEx () til at acceptere nye forbindelser, dette kan bruges på asynkron måde, så du behøver ikke en separat tråd til tilslutning accept og kan bruge trådene, der også behandler dine overlappede/async læse og skrive operationer. [3]

Andre referencer 1


Jeg har skrevet en asynkron klient, der ikke bruger blokering af stikkontakter, så hvis du er interesseret i denne tilgang, så tag et kig på min klient: http://codesprout.blogspot.com/2011/04/asynchronous-http- client.html [4]


Det er en HTTP-klient, men jeg har vist meget lille HTTP-protokolbehandling derinde, det er bare bare .NET-stikkontakter. Serveren ville arbejde på en lignende måde: Du kan udnytte * Async-metoder som [[AsseptAsync.

Andre referencer 2


Under Windows opnås de bedste resultater ved at bruge I/O-afslutningsopkald.


Dette skyldes, at listerne og kølemekanismen er lavet i kernen langt fra den store brugermodus overhead (som trækker din kode ned, hvis du tør gøre det hårde arbejde selv).


Desværre skal Windows I/O-afslutningsopkald allokere mange tråde i målestok, og dette dræber hurtigt forestillingerne (i forhold til Linux-epoll, som kan skalere uafhængigt af antallet af medarbejdertråde dig beslutte at involvere i opgaven).


For nylig opdagede jeg http://gwan.com/en webserver, der kom fra Windows og blev derefter portet under Linux. Og deres forfattere beskriver problemet i detaljer på deres forum. [5]