c - Håndtering af asynkrone stik i WinSock?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger et meddelelsesvindue og WSAAsyncSelect. Hvordan kan jeg holde styr på flere stikkontakter (klienterne) med et meddelelsesvindue?

Bedste reference


Windows Understøtter flere tilstande af sokkeloperation, og du skal være klar, hvilken en du bruger:



  • Blokerer stikkontakter. send og recv blok.

  • Ublusbare stikkontakter: send og returner E\_WOULDBLOCK, og vælg () bruges til at bestemme hvilke stikkontakter der er klar

  • Asynkrone stik: WSAAsyncSelect - sockets post hændelsesmeddelelser til en HWND.

  • EventSockets: WSAEventSelect - sockets signal events.

  • Overlappede stikkontakter: WSASend og WSARecv bruges med stikkontakter ved at passere i OVERLAPPED-strukturerne. Overlappede sokler kan kombineres med IOCompletionPorts og give den bedste skalerbarhed.



Med hensyn til bekvemmelighed er asynkrone stik simpel og understøttet af MFC CAsyncSocket klasse.


Event Sockets er vanskelige at bruge, da det maksimale antal objekter, der kan bruges til WaitForMultipleObjects, er 64.


Overlappede stikkontakter, med IO CompletionPorts, er den mest skalerbare måde at håndtere stikkontakter på og giver Windows-baserede servere mulighed for at skala til titusindvis af stikkontakter.





Efter min erfaring, når du bruger Async Sockets, kommer følgende ting til at tænke på:



  • Håndtering af FD-begivenheder via vinduemeddelelser kan håndtere 'masser' af stikkontakter, men ydeevnen begynder at lide, da alle hændelseshåndtering er lavet i en tråd, serieliseret via en meddelelseskø, der også kan være optaget til at håndtere brugerinteresserede begivenheder, hvis de bruges i en enkelt gevindet GUI app.

  • Hvis du er vært for GUI-vinduer eller timere på samme tråd som mange stikkontakter: WM\_TIMER og WM\_PAINT-meddelelser har lav prioritet, og de oprettes kun, hvis meddelelseskøen er tom. Meget travle stikkontakter kan således forårsage GUI-maleri, eller SetTimer-baseret timing mislykkes.

  • Oprettelse af en dedikeret arbejdstråd til at håndtere dine stikkontakter, hvis du er vært for en GUI, løser disse problemer. I betragtning af at arbejdstrådens tråd vil have en meddelelsessløjfe, kan du bruge meddelelseskøen til trådkommandoer - bare post WM\_APP-meddelelser til tråden.

  • Den nemmeste måde at kortlægge FD-tilbagekald til dine sokobjekter er at oprette et Array of SocketObjects for hver HWND, der modtager meddelelser, og brug derefter WM\_USER + -indeks som meddelelses-ID hver gang du ringer til WASAsyncSelect. Når du modtager meddelelser i området WM\_USER til WM\_USER + (array størrelse), kan du hurtigt udtrække det tilsvarende statobjekt. WM\_USER er 0x400, og WM\_APP er 0x8000, så du kan indeksere op til 31744 sockets pr. Meddelelsesvindue ved hjælp af denne metode.

  • Brug ikke en statisk rækkevidde. Du skal forbinde arrayet med vinduet, da du måske vil oprette stikkontakter på flere tråde. Hver tråd skal have sin egen meddelelsessløjfe og meddelelsesvindue.

  • HWND\_MESSAGE er din ven


Andre referencer 1


Parameteren wParam i vinduesmeddelelsen, som du fortæller WSAAsyncSelect() skal angive den stikkontakt, der udløste meddelelsen. Dette fremgår tydeligt af dokumentationen WSAAsyncSelect(): [4]



  Når et af de nominerede netværk
  Hændelser sker på den specificerede stik
  s, programvinduet hWnd
  modtager besked wMsg. WParam
  parameter identificerer stikket på
  som en netværksbegivenhed har fundet sted.
  Det lave ord af lParam angiver
  netværksbegivenhed, der er opstået. Det
  Højt ord af lParam indeholder en fejl
  kode. Fejlkoden er en fejl som
  defineret i Winsock2.h.