рд╡рд┐рдВрдбреЛрдЬ рд╕реЙрдХреЗрдЯреНрд╕, IOCP, рдФрд░ рдбреЗрд▓реНрдлреА

рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛


рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдореБрдЭреЗ рд╡рд┐рдВрдбреЛрдЬ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдкреНрд░рднрд╛рд╡реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ред рдХрд╛рд░реНрдп рд╡реНрдпрд╕реНрдд рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИред рдХреЗрд╡рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рднрд╛рд╖рд╛, рдбреЗрд▓реНрдлреА, рдпрд╣рд╛рдБ рдЕрд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рддреАрдд рд╣реЛрдЧреАред
рдореИрдВ рдЖрдИ / рдУ рдХрдореНрдкреНрд▓реАрд╢рди рдкреЛрд░реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрд╛рдо рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред Microsoft рдЕрдкрдиреЗ рд╕рд╛рд╣рд┐рддреНрдп рдореЗрдВ рдЗрд╕ рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдмрд╣реБрдд рд╕реЗ рд▓реЛрдЧ рдЗрд╕рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд┐рд░реНрдл рдорд╛рдорд▓реЗ рдореЗрдВ, рдореИрдВ MSDN рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реВрдВрдЧрд╛ред рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдХрд╛ рд╕рд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╕рд┐рд╕реНрдЯрдо рдШрдЯрдирд╛рдУрдВ рдХреА рдПрдХ рдЕрддреНрдпрдзрд┐рдХ рдХреБрд╢рд▓ рдХрддрд╛рд░ рдХрд╛ рдЖрдпреЛрдЬрди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрд╕реЗ рдереНрд░реЗрдб рдкреВрд▓ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЖрдХрд╛рд░ рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рдХреЛрд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рджреНрд╡рд╛рд░рд╛ рдЪреБрдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдП рдЧрдП рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдЗрдирдкреБрдЯ-рдЖрдЙрдЯрдкреБрдЯ рд╕рдВрдЪрд╛рд▓рди рдХреА рдПрдХ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдлрд╛рдпрджреЗ рд╣реИрдВред рддреИрдпрд╛рд░ рд╕реНрд░реЛрдд рддреБрд░рдВрдд (рдмреЗрд╣рддрд░) рдпрд╣рд╛рдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ ред рд╕рдм рдХреБрдЫ рд╕рд╣реА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдХрд░реЗрдЧрд╛ред

рд░реЛрдбрдореИрдк


рдореИрдВ, рдПрдХ рддрд░рд╣ рд╕реЗ, рд╡рд╕реНрддреБрдУрдВ рдФрд░ рдЗрдирдкреБрдЯ-рдЖрдЙрдЯрдкреБрдЯ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд╕рдВрдЧрдарди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣рд░ рдЪреАрдЬ рдореЗрдВ Node.Js рдХреА рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рдХрд╛ рдкрд╛рд▓рди рдХрд░реВрдВрдЧрд╛ред
рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рдкрд╣рд▓рд╛ рдЖрдЗрдЯрдо рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдиреЗрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рджреЛрдиреЛрдВ рд╡рд░реНрдЧреЛрдВ рдореЗрдВ рдПрдХ рд╣реА рдмрд┐рдВрджреБ рдкрд░ рдПрдХ рд╕рд╛рде рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрдЧреАред
рд╕рднреА рдмрдирд╛рдП рдЧрдП рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рд╕реЙрдХреЗрдЯ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдФрд░ рдПрдХ рдереНрд░реЗрдб рдкреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдПрдХ рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдПрдХ рдЖрд╡реЗрджрди рдореЗрдВ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реЙрдХреЗрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд┐рд▓реНрдХреБрд▓ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдШрдЯрдирд╛ рдореЙрдбрд▓ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ, рдореИрдВ рдХрдХреНрд╖рд╛рдПрдВ рдирд╣реАрдВ рдмрд▓реНрдХрд┐ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реВрдВрдЧрд╛ред рдпрд╣ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрд╡рдВрдЯрд┐рдд рдореЗрдореЛрд░реА рдХреА рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдЕрдВрддрд┐рдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╕реЗ рд╣рдЯрд╛ рджреА рдЬрд╛рддреА рд╣реИред рд╡реИрд╕реЗ рднреА, рдпрд╣рд╛рдВ рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдЯреНрд░реИрдХ рдХрд░рдирд╛ рдпрд╛ рддреЛ рдмрд╣реБрдд рдорд╣рдВрдЧрд╛ рд╣реИ рдпрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕рдВрднрд╡ рд╣реИред рдореЙрдбреНрдпреВрд▓ рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХрд╛рдо рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред

рдФрд░ рдЗрд╕рд▓рд┐рдП, рдЖрд░рдВрднреАрдХрд░рдг рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реЛрддреА рд╣реИ, рдЬреЛ рд╕реВрдЪреА рдмрд┐рдВрджреБ рдХреЛ рдмрд┐рдВрджреБ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИред
procedure Init; var WSAData: TWsaData; i: Integer; begin gClients := TProtoStore.Create; gListeners := TProtoStore.Create; gServerClients := TProtoStore.Create; if WSAStartup(MAKEWORD(2, 2), WSAData) <> 0 then raise IOCPClientException.Create(sErrorInit_WSAtartup); gIOCP := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, CPUCount * 2); if gIOCP = INVALID_HANDLE_VALUE then raise IOCPClientException.Create(sErrorInit_CreateIoCompletionPort); for i := 1 to CPUCount * 2 do begin SetLength(gWorkers, Length(gWorkers) + 1); gWorkers[Length(gWorkers) - 1] := TWorkerThread.Create(); end; gListenerAcceptEvent := WSACreateEvent; if gListenerAcceptEvent = WSA_INVALID_EVENT then raise IOCPClientException.Create(sErrorInit_WSACreateEvent); gServerClientsCloseEvent := WSACreateEvent; if gServerClientsCloseEvent = WSA_INVALID_EVENT then raise IOCPClientException.Create(sErrorInit_WSACreateEvent); gClisentsConnectAndCloseEvents := WSACreateEvent; if gClisentsConnectAndCloseEvents = WSA_INVALID_EVENT then raise IOCPClientException.Create(sErrorInit_WSACreateEvent); gClientSocketEventThread := TSocketEventThread.Create (gClisentsConnectAndCloseEvents, gClients, ET_EVENT_SIGNALED); gClientSocketEventThread.Start; gServerClientsSocketEventThread := TSocketEventThread.Create (gServerClientsCloseEvent, gServerClients, ET_EVENT_SIGNALED); gServerClientsSocketEventThread.Start; gServerSocketEventThread := TSocketEventThread.Create(gListenerAcceptEvent, gListeners, ET_EVENT_SIGNALED); gServerSocketEventThread.Start; end; 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ CreateIoCompletionPort рдлрд╝рдВрдХреНрд╢рди рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдмрдирд╛рддрд╛ рд╣реИред
рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рд╣реА TSocketEventThread рд╕реНрдЯреНрд░реАрдо рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рднрд┐рдиреНрди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕реЙрдХреЗрдЯреНрд╕ рдкрд░ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рд╡рд░реНрдЧ рдХреА рдзрд╛рд░рд╛рдПрдБ рдПрдХ рдРрд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреА рд╣реИрдВ рдЬреЛ рд╕реЙрдХреЗрдЯ рдШрдЯрдирд╛рдУрдВ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреА рд╣реИ, рдФрд░ рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреА рдШрдЯрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рддреБрд░рдВрдд рд╕рдВрджреЗрд╢ (рдкреНрд░рддреНрдпреЗрдХ рд╕реЙрдХреЗрдЯ рдХреЗ рд▓рд┐рдП рдЬреЛ рдпрд╣ рдзрд╛рд░рд╛ рдХрд╛рд░реНрдп рдХрд░рддреА рд╣реИ) рдХреЗ рд▓рд┐рдП рдХрддрд╛рд░рдмрджреНрдз рд╕рдВрджреЗрд╢ рджреЗрддреА рд╣реИред
 procedure TSocketEventThread.WaitForClientsEvents; var WaitResult: DWORD; const TimeOut: DWORD = 100; begin WaitResult := WSAWaitForMultipleEvents(1, @fEvent, FALSE, TimeOut, FALSE); if WaitResult = WSA_WAIT_FAILED then raise IOCPClientException.Create (sErrorWaitForClientsEvents_WSAWaitForMultipleEvents); if WaitResult = WSA_WAIT_EVENT_0 then begin if not WSAResetEvent(fEvent) then raise IOCPClientException.Create (sErrorWaitForClientsEvents_WSAResetEvent); fStore.Post(fKey); end; end; 

рдпрд╣рд╛рдБ рд╡рд┐рдзрд┐ fStore.Post (fKey) рд╣реИ; рдпрд╣ рдХрддрд╛рд░ рдХреЛ рд╕рдВрджреЗрд╢ рднреА рднреЗрдЬрддрд╛ рд╣реИред
 procedure TProtoStore.Post(CompletionKey: DWORD); var i: Integer; begin fLock.Enter; try for i := 0 to Length(ProtoArray) - 1 do begin ProtoArray[i]._AddRef; if not PostQueuedCompletionStatus(gIOCP, 0, CompletionKey, POverlapped(ProtoArray[i])) then begin ProtoArray[i]._Release; raise IOCPClientException.Create(sErrorPost_PostQueuedCompletionStatus); end; end; finally fLock.Leave; end; end; 

рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдиреЛрдЯ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд╕рд╛рде рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИред
_AddRef рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ "рдХрддрд╛рд░ рдореЗрдВ" рд╣реИ рдФрд░ рдЗрд╕реЗ рдирд╖реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред (рдмрд╛рдж рдореЗрдВ, рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд╛рдж, _Release рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛)ред PostQueuedCompletionStatus рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реАрдзреЗ рд╕рдВрджреЗрд╢ рдХреЛ рдХрддрд╛рд░рдмрджреНрдз рдХрд░рддреА рд╣реИред
рдкреВрд▓ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджреЗрд╢ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░реЗрдЧрд╛ред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред
 procedure TWorkerThread.ProcessIOCP; var NumberOfBytes: DWORD; CompletionKey: NativeUInt; Overlapped: POverlapped; Proto: TIOCPSocketProto; begin if not((not GetQueuedCompletionStatus(gIOCP, NumberOfBytes, CompletionKey, Overlapped, INFINITE)) and (Overlapped = nil)) then begin if CompletionKey = ET_EVENT_SIGNALED then begin Proto := TIOCPSocketProto(Overlapped); with Proto do begin IOCPProcessEventsProc(); _Release; end end else if CompletionKey <> 0 then begin Proto := TIOCPSocketProto(CompletionKey); if Proto.IOCPProcessIOProc(NumberOfBytes, Overlapped) then Proto._Release; end; end end; 

GetQueuedCompletionStatus рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрддрд╛рд░ рд╕реЗ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдЧрд▓рд╛, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╕рдВрджреЗрд╢ рдкреВрд░реНрдг рдЗрдирдкреБрдЯ / рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рд╣реИ рдпрд╛ рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдпрд╣ рд╕рдВрджреЗрд╢ рд╣реИред рдХрддрд╛рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреЛ рддрд░реАрдХреЗ рдпрд╣рд╛рдВ рджрд┐рдЦрд╛рдП рдЧрдП рд╣реИрдВ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕реЙрдХреЗрдЯ рдХреНрд▓рд╛рд╕ рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХред
рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХреАрдХреГрдд рд╣реИ, рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреВрд░реНрд╡рдЬ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЖрдо рд╣реИрдВрдбрд▓рд░ рд╣реЛрддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рдкреБрдирд░реНрд╡рд┐рддреНрдд рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред
рд╕реЙрдХреЗрдЯ рдШрдЯрдирд╛рдУрдВ рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рддрдВрддреНрд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
 procedure TIOCPSocketProto.IOCPProcessEventsProc(); var WSAEvents: TWsaNetworkEvents; AcceptedSocket: TSocket; RemoteAddress: string; begin if fStateLock <> CLI_SOCKET_LOCK_CLOSED then begin fClosingLock.BeginRead; try if (fStateLock <> CLI_SOCKET_LOCK_CLOSED) then if WSAEnumNetworkEvents(fSocket, 0, WSAEvents) <> SOCKET_ERROR then begin if ((WSAEvents.lNetworkEvents and FD_CONNECT) <> 0) then begin if 0 = WSAEvents.iErrorCode[FD_CONNECT_BIT] then InterlockedExchange(fStateLock, CLI_SOCKET_LOCK_CONNECTED); CallOnConnect; end; if ((WSAEvents.lNetworkEvents and FD_CLOSE) <> 0) and (0 = WSAEvents.iErrorCode[FD_CLOSE_BIT]) then CallOnClose; if ((WSAEvents.lNetworkEvents and FD_ACCEPT) <> 0) and (0 = WSAEvents.iErrorCode[FD_ACCEPT_BIT]) then begin AcceptedSocket := DoAccept(RemoteAddress); if AcceptedSocket <> INVALID_SOCKET then begin fClientClass.Create(AcceptedSocket, fOnConnect, fOnClose, RemoteAddress).Prepare; end; end; end finally fClosingLock.EndRead; end; end; end; 

TMultiReadExclusiveWriteSynchronizer рд╡рд░реНрдЧ рджрд┐рд▓рдЪрд╕реНрдк рддрд░реАрдХреЗ рд╕реЗ рдпрд╣рд╛рдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реЙрдХреЗрдЯ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдФрд░ рдкреВрд▓ рдореЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдзрд╛рдЧреЗ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдирд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (fClosingLock.BeginRead)ред рд╕реЙрдХреЗрдЯ рдХреЗ рд╕рд╛рде рд╕рднреА рд╕рдВрдЪрд╛рд▓рди рдЗрд╕ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рд░реАрдб рдСрдкрд░реЗрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд╕реЙрдХреЗрдЯ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдФрд░ рд╕рдорд╛рдкрди рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдЫреЛрдбрд╝рдХрд░ - рд╡реЗ рдСрдкрд░реЗрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд▓рд┐рдП рд╕рдВрд╕рд╛рдзрди рдХреЗ рдЕрдирдиреНрдп рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдХреЗ рд╕рд╛рде рд╣реА рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЕрдиреНрдп рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╣реИред
рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдПрдХрдорд╛рддреНрд░ рдЪреАрдЬ рдПрдХ рдирдП рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рд░реНрд╡рд░, DoAccept рд╡рд┐рдзрд┐ рд╕реЗ рдЬреЛрдбрд╝ рд░рд╣реА рд╣реИред
 function TIOCPSocketProto.DoAccept(var RemoteAddress: string): TSocket; var addr: TSockAddr; addrlen: Integer; dwCallbackData: NativeUInt; RemoteAddrLen: DWORD; begin dwCallbackData := NativeUInt(self); addrlen := SizeOf(addr); Result := WSAAccept(fSocket, @addr, @addrlen, ServerAcceptCallBack, dwCallbackData); if Result <> INVALID_SOCKET then begin SetLength(RemoteAddress, 255); RemoteAddrLen := Length(RemoteAddress); if WSAAddressToString(addr, addrlen, nil, PChar(@RemoteAddress[1]), RemoteAddrLen) = SOCKET_ERROR then raise IOCPClientException.Create(sErrorAccept_WSAAddressToString); SetLength(RemoteAddress, RemoteAddrLen - 1) end end; 

рдпрд╣рд╛рдБ рдореБрдЦреНрдп рдмрд┐рдВрджреБ WSAAccept рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЖрдкрдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ FD_CONNECT рдИрд╡реЗрдВрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗред
рддрдерд╛рдХрдерд┐рдд рдХрд╛рд▓рд╛рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрдЧрдард┐рдд рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рдкрд╕рдВрджреАрджрд╛ рддрд░реАрдХрд╛ рд╣реИред
рд╣рдо рдФрд░ рдЖрдЧреЗ рдмрдврд╝реЗрдВред рдЗрдирдкреБрдЯ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд╕рдВрдЧрдарди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╣рдо рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рд░реАрдб рдСрдкрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдРрд╕рд╛ рдХрд░реЗрдВрдЧреЗред
 procedure TIOCPSocketProto.Read(Length: DWORD; OnRead, OnReadProcess: TOnReadEvent); var Bytes, Flags: DWORD; WsaBuf: TWsaBuf; begin fClosingLock.BeginRead; try if fStateLock = CLI_SOCKET_LOCK_CONNECTED then begin if InterlockedCompareExchange(fReadLock, IO_PROCESS, IO_IDLE) = IO_IDLE then begin fOnRead := OnRead; fOnReadProcess := OnReadProcess; fReaded := 0; fReadBufLength := Length; fReadBuffer := nil; GetMem(fReadBuffer, Length); if fReadBuffer <> nil then begin Bytes := 0; FillChar(fOverlappedRead, SizeOf(fOverlappedRead), 0); WsaBuf.buf := fReadBuffer; WsaBuf.len := fReadBufLength; Flags := 0; Bytes := 0; _AddRef; if (WSARecv(fSocket, @WsaBuf, 1, Bytes, Flags, @fOverlappedRead, nil) = SOCKET_ERROR) and (WSAGetLastError <> WSA_IO_PENDING) then begin FreeMem(fReadBuffer, Length); InterlockedExchange(fReadLock, IO_IDLE); _Release; raise IOCPClientException.Create(sErrorRead_WSARecv); end; end else raise IOCPClientException.Create(sErrorRead_GetMem); end else raise IOCPClientException.Create(sErrorRead_InProcess); end else raise IOCPClientException.Create(sErrorRead_NotConnected); finally fClosingLock.EndRead; end; end; 

рдпрд╣рд╛рдБ рдореБрдЭреЗ рдЗрдВрдЯрд░рд▓реЙрдХрд┐рдВрдЧ рд▓реЙрдХрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрдбрд╝рд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрд╣реБрдд рддреЗрдЬрд╝ рд╣реИ рдФрд░ I / O рд╡рд┐рдХрд▓реНрдк рдХреЛ рд╡рд╛рдкрд╕ рдмреБрд▓рд╛рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдореЗрдВ рдХрдЯреМрддреА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИред рдореЗрдореЛрд░реА рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди рдореЗрдВ рдПрдХ рдмрд╛рд░ рдмрдлрд░ рдХреЗ рддрд╣рдд рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдЧрд▓рд╛, рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдореЛрдб рдореЗрдВ рд╕реЙрдХреЗрдЯ рд╕реЗ рдкрдврд╝рдирд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ AddRef рдХреЗ рд╕рд╛рде "рдЪрд┐рд╣реНрдирд┐рдд" рднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдХрддрд╛рд░ рдореЗрдВ рд░рд╣рддреЗ рд╣реБрдП рдЙрд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдкреИрдХреЗрдЯ рдкрдврд╝рдиреЗ рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдВрджреЗрд╢ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкрдВрдХреНрддрд┐рдмрджреНрдз рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдкреВрд░рд╛ рдЗрдирдкреБрдЯ / рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рд╕реЗ рдЪреБрдирд╛ рдЬрд╛рддрд╛ рд╣реИред
 function TIOCPSocketProto.IOCPProcessIOProc(NumberOfBytes: DWORD; Overlapped: POverlapped): Boolean; var Bytes, Flags: DWORD; WsaBuf: TWsaBuf; begin Result := FALSE; fClosingLock.BeginRead; try if Overlapped = @fOverlappedRead then begin if NumberOfBytes <> 0 then begin if fReadLock = IO_PROCESS then begin inc(fReaded, NumberOfBytes); if fReaded < fReadBufLength then begin CallOnReadProcess; WsaBuf.buf := fReadBuffer; inc(WsaBuf.buf, fReaded); WsaBuf.len := fReadBufLength; dec(WsaBuf.len, fReaded); Flags := 0; Bytes := 0; if (WSARecv(fSocket, @WsaBuf, 1, Bytes, Flags, @fOverlappedRead, nil) = SOCKET_ERROR) and (WSAGetLastError <> WSA_IO_PENDING) then begin CallOnRead; Result := True; end end else begin CallOnReadProcess; CallOnRead; Result := True; end; end end else begin CallOnRead; Result := True; end; end else if Overlapped = @fOverlappedWrite then begin if NumberOfBytes <> 0 then begin if fWriteLock = IO_PROCESS then begin inc(fWrited, NumberOfBytes); if fWrited < fWriteBufLength then begin CallOnWriteProcess; WsaBuf.buf := fWriteBuffer; inc(WsaBuf.buf, fWrited); WsaBuf.len := fWriteBufLength; dec(WsaBuf.len, fWrited); Flags := 0; Bytes := 0; if (WSASend(fSocket, @WsaBuf, 1, Bytes, Flags, @fOverlappedWrite, nil) = SOCKET_ERROR) and (WSAGetLastError <> WSA_IO_PENDING) then begin CallOnWrite; Result := True; end end else begin CallOnWriteProcess; CallOnWrite; Result := True; end; end end else begin CallOnWrite; Result := True; end; end finally fClosingLock.EndRead; end; end; 

рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╕рд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЙрд╕ рд╕рдордп рддрдХ рд╕реЙрдХреЗрдЯ рдореЗрдВ рдкрдврд╝рдиреЗ рдпрд╛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ рдЬрдм рдЖрд╡рдВрдЯрд┐рдд рдмрдлрд░ рднрд░рд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБ рдУрд╡рд░рд▓реИрдб рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдСрдкрд░реЗрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рд╣реИред рдпрд╣ рд▓рд┐рдВрдХ рдХрддрд╛рд░ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреА рдХреЗрд╡рд▓ рдХрдХреНрд╖рд╛ рдХреЗ рд╕рдВрдмрдВрдзрд┐рдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрд░рдЪрдирд╛рдПрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВред
рдпрд╣ рднреА рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╣реИ рдХрд┐ рдпрджрд┐ рд░реАрдб / рд░рд╛рдЗрдЯ рдСрдкрд░реЗрд╢рди рддреБрд░рдВрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдпрд╣ рдЕрднреА рднреА рдХрддрд╛рд░ рдореЗрдВ рдЖ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЗрд╕реЗ рдПрдкреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрд╣ рд╕реЙрдХреЗрдЯ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдиреЗ рдФрд░ рдХрддрд╛рд░ рдмрдирд╛рдиреЗ рдкрд░ рднреА рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИред
 constructor TIOCPClientSocket.Create(RemoteAddress: string; OnConnect, OnClose: TOnSimpleSocketEvenet); var lRemoteAddress: TSockAddr; lRemoteAddressLength: Integer; begin inherited Create(); fStore := gClients; fOnConnect := OnConnect; fOnClose := OnClose; fStateLock := 0; fRemoteAddressStr := RemoteAddress; fSocket := WSASocket(AF_INET, SOCK_STREAM, 0, nil, 0, WSA_FLAG_OVERLAPPED); if fSocket = INVALID_SOCKET then raise IOCPClientException.Create(sErrorTIOCPClientSocket_WSASocket); if (WSAEventSelect(fSocket, gClisentsConnectAndCloseEvents, FD_CONNECT or FD_CLOSE) = SOCKET_ERROR) then raise IOCPClientException.Create(sErrorTIOCPClientSocket_WSAEventSelect); if CreateIoCompletionPort(fSocket, gIOCP, NativeUInt(self), 0) = 0 then raise IOCPClientException.Create (sErrorTIOCPClientSocket_CreateIoCompletionPort); fStateLock := CLI_SOCKET_LOCK_CREATED; fStore.Add(self); lRemoteAddressLength := SizeOf(lRemoteAddress); lRemoteAddress.sa_family := AF_INET; if WSAStringToAddress(PChar(@fRemoteAddressStr[1]), AF_INET, nil, lRemoteAddress, lRemoteAddressLength) = SOCKET_ERROR then raise IOCPClientException.Create (sErrorTIOCPClientSocket_WSAStringToAddress); if (WSAConnect(fSocket, lRemoteAddress, lRemoteAddressLength, nil, nil, nil, nil) = SOCKET_ERROR) and (WSAGetLastError <> WSAEWOULDBLOCK) then raise IOCPClientException.Create(sErrorTIOCPClientSocket_WSAConnect); end; 

рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЙрдХреЗрдЯ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рд╕реЙрдХреЗрдЯ (WSASocket) рдХреЛ рддреБрд░рдВрдд рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХрддрд╛рд░ (CreateIoCompletionPort) рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдИрд╡реЗрдВрдЯ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрдиреЗрдХреНрд╢рди рдлрд╝рдВрдХреНрд╢рди (WSAConnect) рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рдХрдиреЗрдХреНрд╢рди рдХрд╛ рддрдереНрдп рдЙрд╕ рдзрд╛рд░рд╛ рдореЗрдВ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ рдЬрд┐рд╕реЗ рдкрд╣рд▓реЗ рдорд╛рдирд╛ рдЧрдпрд╛ рдерд╛ (рд╕реЙрдХреЗрдЯреНрд╕ рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА рдзрд╛рд░рд╛)ред рдпрд╣ рдмрджрд▓реЗ рдореЗрдВ рдЗрд╕ рдШрдЯрдирд╛ рдХреЛ рдХрддрд╛рд░ рдореЗрдВ рдЦрдбрд╝рд╛ рдХрд░реЗрдЧрд╛ред

рдЙрдкрд╕рдВрд╣рд╛рд░


рдпрд╣ рдЖрд▓реЗрдЦ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдЗрд╡реЗрдВрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛рдиреЗ рдХреА рд╕рдлрд▓ рддрдХрдиреАрдХреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИред
рдореИрдВ рдбреЗрд▓реНрдлреА рдХреЗ рд▓рд┐рдП рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рд╡рд╛рд▓реЗ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд░реНрдЧ рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред рдпрд╣ рд╡рд┐рд╖рдп рдЖрдо рддреМрд░ рдкрд░ рдмреЗрд╣рдж рдЦрд░рд╛рдм рддрд░реАрдХреЗ рд╕реЗ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ IOCP (рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд┐рдХ рдкреНрд░рджрд╛рддрд╛рдУрдВ рдФрд░ Winsock Secure Socket Extensions) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рдПрдХ рдФрд░ 2 - 3 рдкрджреЛрдВ рдХреЗ рд╕рд╛рде рдЗрд╕ рдкреНрд░рдХрд╛рд╢рди рдХреЛ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреА рдореЗрд░реА рдпреЛрдЬрдирд╛ рд╣реИред рдкреВрд░рд╛ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдпрд╣рд╛рдБ рд╣реИ ред

Source: https://habr.com/ru/post/In145140/


All Articles