IOCPComp.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:23k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit IOCPComp;
  2. interface
  3. {$IFDEF VER150}
  4.   {$WARN UNSAFE_TYPE OFF}
  5.   {$WARN UNSAFE_CODE OFF}
  6.   {$WARN UNSAFE_CAST OFF}
  7. {$ENDIF}
  8. uses
  9.   Windows, Messages, WinSock2, Classes,ScktComp, SysUtils;
  10. const
  11.   MAX_BUFSIZE = 4096;
  12.   WM_CLIENTSOCKET = WM_USER + $2000;
  13. type
  14.   TCMSocketMessage = packed record
  15.     Msg: Cardinal;
  16.     Socket: TSocket;
  17.     SelectEvent: Word;
  18.     SelectError: Word;
  19.     Result: Longint;
  20.   end;
  21.   TSocketEvent = (seInitIOPort, seInitSocket,  seConnect, seDisconnect,
  22.     seListen, seAccept, seWrite, seRead);
  23.   TErrorEvent = (eeGeneral, eeSend, eeReceive, eeConnect, eeDisconnect, eeAccept);
  24.   PPerHandleData = ^TPerHandleData;
  25.   TPerHandleData = packed record
  26.     Overlapped: OVERLAPPED;
  27.     wsaBuffer: WSABUF;
  28.     Event: TSocketEvent;
  29.     IsUse: Boolean;
  30.     Buffer: array [0..MAX_BUFSIZE - 1] of Char;
  31.   end;
  32.   PBlock = ^TBlock;
  33.   TBlock = packed record
  34.     Data: TPerHandleData;
  35.     IsUse: Boolean;
  36.   end;
  37.   EMemoryBuffer = class(Exception);
  38.   ESocketError = class(Exception);
  39.   TCustomSocket = class;
  40.   TServerClientSocket = class;
  41.   TOnDataEvent = function(Socket: TCustomSocket; Data: Pointer; Count: Integer): Integer of object;
  42.   TSocketErrorEvent = procedure(Socket: TCustomSocket; ErrorEvent: TErrorEvent; var ErrCode: Integer) of object;
  43.   TSocketEventEvent = procedure(Socket: TCustomSocket; SocketEvent: TSocketEvent) of object;
  44.   TMemoryBuffer = class
  45.   private
  46.     FList: TList;
  47.     FSocket: TCustomSocket;
  48.     function GetCount: Integer;
  49.     function GetBlock(const Index: Integer): PBlock;
  50.   protected
  51.     property Count: Integer read GetCount;
  52.     property Blocks[const Index: Integer]: PBlock read GetBlock;
  53.   public
  54.     constructor Create(ASocket: TCustomSocket); overload;
  55.     constructor Create(ASocket: TCustomSocket; BlockCount: Integer); overload;
  56.     destructor Destroy; override;
  57.     function AllocBlock: PBlock;
  58.     procedure RemoveBlock(Block: PBlock);
  59.   end;
  60.   TCustomSocket = class
  61.   private
  62.     FSocket: TSocket;
  63.     FActive: Boolean;
  64.     FInitLock: Boolean;
  65.     FLock: TRTLCriticalSection;
  66.     FOnRead: TOnDataEvent;
  67.     FOnErrorEvent: TSocketErrorEvent;
  68.     FOnEventEvent: TSocketEventEvent;
  69.     function GetRemoteAddress: string;
  70.     function GetRemoteHost: string;
  71.     procedure DoRead(Data: Pointer; Count: Integer);
  72.   protected
  73.     procedure SetActive(Value: Boolean); virtual; abstract;
  74.     procedure Event(SocketEvent: TSocketEvent); virtual;
  75.     procedure Error(ErrorEvent: TErrorEvent; var ErrCode: Integer); virtual;
  76.     property OnRead: TOnDataEvent read FOnRead write FOnRead;
  77.     property OnErrorEvent: TSocketErrorEvent read FOnErrorEvent write FOnErrorEvent;
  78.     property OnEventEvent: TSocketEventEvent read FOnEventEvent write FOnEventEvent;
  79.   public
  80.     constructor Create(ASocket: TSocket);
  81.     destructor Destroy; override;
  82.     procedure Close;
  83.     procedure Open;
  84.     procedure Lock;
  85.     procedure UnLock;
  86.     function Read(var Buf; Count: Integer): Integer; virtual;
  87.     function Write(var Buf; Count: Integer): Integer; virtual;
  88.     property SocketHandle: TSocket read FSocket;
  89.     property Active: Boolean read FActive write SetActive;
  90.     property RemoteHost: string read GetRemoteHost;
  91.     property RemoteAddress: string read GetRemoteAddress;
  92.   end;
  93.   TCustomerServerSocket = class(TCustomSocket)
  94.   private
  95.     FOnClientRead: TOnDataEvent;
  96.     FOnClientError: TSocketErrorEvent;
  97.     FOnClientEvent: TSocketEventEvent;
  98.   protected
  99.     function DoClientRead(ASocket: TCustomSocket; AData: Pointer; ACount: Integer): Integer;
  100.     procedure ClientSocketError(ASocket: TCustomSocket;
  101.       ErrorEvent: TErrorEvent; var ErrCode: Integer);
  102.     procedure ClientSocketEvent(ASocket: TCustomSocket; SocketEvent: TSocketEvent);
  103.   public
  104.     property OnClientRead: TOnDataEvent read FOnClientRead write FOnClientRead;
  105.     property OnClientError: TSocketErrorEvent read FOnClientError write FOnClientError;
  106.     property OnClientEvent: TSocketEventEvent read FOnClientEvent write FOnClientEvent;
  107.     property OnErrorEvent;
  108.     property OnEventEvent;
  109.   end;
  110.   TGetSocketEvent = procedure(Socket: TSocket; var ClientSocket: TServerClientSocket) of object;
  111.   TServerSocket = class(TCustomerServerSocket)
  112.   private
  113.     FPort: Integer;
  114.     FAddr: TSockAddr;
  115.     FAcceptThread: TThread;
  116.     FCompletionPort: THandle;
  117.     FClients: TList;
  118.     FThreads: TList;
  119.     FHandle: THandle;
  120.     FBuffer: TMemoryBuffer;
  121.     FOnGetSocket: TGetSocketEvent;
  122.     procedure SetPort(Value: Integer);
  123.     procedure RegisterClient(ASocket: TCustomSocket);
  124.     procedure RemoveClient(ASocket: TCustomSocket);
  125.     procedure WMClientClose(var Message: TCMSocketMessage); message WM_CLIENTSOCKET;
  126.     procedure WndProc(var Message: TMessage);
  127.     function FindClientSocket(ASocket: TSocket): TCustomSocket;
  128.     function GetClientCount: Integer;
  129.     function GetClients(const Index: Integer): TServerClientSocket;
  130.   protected
  131.     procedure InternalOpen;
  132.     procedure InternalClose;
  133.     procedure SetActive(Value: Boolean); override;
  134.     property CompletionPort: THandle read FCompletionPort;
  135.     function IsAccept(Socket: TSocket): Boolean; virtual;
  136.   public
  137.     constructor Create;
  138.     destructor Destroy; override;
  139.     procedure Accept(ASocket: TSocket; ACompletionPort: THandle);
  140.     property Handle: THandle read FHandle;
  141.     property Port: Integer read FPort write SetPort;
  142.     property ClientCount: Integer read GetClientCount;
  143.     property Clients[const Index: Integer]: TServerClientSocket read GetClients;
  144.     property OnGetSocket: TGetSocketEvent read FOnGetSocket write FOnGetSocket;
  145.   end;
  146.   TServerClientSocket = class(TCustomSocket)
  147.   private
  148.     FBlock: TList;
  149.     FBuffer: TMemoryBuffer;
  150.     FServerSocket: TServerSocket;
  151.     function AllocBlock: PBlock;
  152.     function PrepareRecv(Block: PBlock = nil): Boolean;
  153.     function WorkBlock(var Block: PBlock; Transfered: DWORD): DWORD;
  154.   protected
  155.     procedure SetActive(Value: Boolean); override;
  156.   public
  157.     constructor Create(AServerSocket: TServerSocket; ASocket: TSocket);
  158.     destructor Destroy; override;
  159.     function Read(var Buf; Count: Integer): Integer; override;
  160.     function Write(var Buf; Count: Integer): Integer; override;
  161.   end;
  162.   TSocketThread = class(TThread)
  163.   private
  164.     FServer: TServerSocket;
  165.   public
  166.     constructor Create(AServer: TServerSocket);
  167.   end;
  168.   TAcceptThread = class(TSocketThread)
  169.   protected
  170.     procedure Execute; override;
  171.   end;
  172.   TWorkerThread = class(TSocketThread)
  173.   protected
  174.     procedure Execute; override;
  175.   end;
  176. implementation
  177. uses RTLConsts;
  178. const
  179.   SHUTDOWN_FLAG = $FFFFFFFF;
  180.   BlockSize: Word = SizeOf(TBlock);
  181. var
  182.   WSData: TWSAData;
  183. { TMemoryBuffer }
  184. constructor TMemoryBuffer.Create(ASocket: TCustomSocket);
  185. begin
  186.   Create(ASocket, 200);
  187. end;
  188. constructor TMemoryBuffer.Create(ASocket: TCustomSocket; BlockCount: Integer);
  189. var
  190.   I: Integer;
  191.   P: PBlock;
  192. begin
  193.   inherited Create;
  194.   FSocket := ASocket;
  195.   FList := TList.Create;
  196.   for I := 0 to BlockCount - 1 do
  197.   begin
  198.     New(P);
  199.     FillChar(P^, BlockSize, 0);
  200.     FList.Add(P);
  201.   end;
  202. end;      
  203. destructor TMemoryBuffer.Destroy;
  204. var
  205.   I: Integer;
  206. begin
  207.   for I := 0 to FList.Count - 1 do
  208.     FreeMem(FList[I]);
  209.   FList.Free;
  210.   inherited Destroy;
  211. end;
  212. function TMemoryBuffer.AllocBlock: PBlock;
  213. var
  214.   I: Integer;
  215. begin
  216.   FSocket.Lock;
  217.   try
  218.     Result := nil;
  219.     for I := 0 to FList.Count - 1 do
  220.     begin
  221.       Result := FList[I];
  222.       if not Result.IsUse then
  223.         break;
  224.     end;
  225.     if not Assigned(Result) or Result.IsUse then
  226.     begin
  227.       New(Result);
  228.       FList.Add(Result);
  229.     end;
  230.     FillChar(Result^.Data, SizeOf(Result^.Data), 0);
  231.     Result^.IsUse := True;
  232.   finally
  233.     FSocket.UnLock;
  234.   end;
  235. end;
  236. procedure TMemoryBuffer.RemoveBlock(Block: PBlock);
  237. begin
  238.   FSocket.Lock;
  239.   try
  240.     Block.IsUse := False;
  241.   finally
  242.     FSocket.UnLock;
  243.   end;
  244. end;
  245. function TMemoryBuffer.GetCount: Integer;
  246. begin
  247.   Result := FList.Count;
  248. end;
  249. function TMemoryBuffer.GetBlock(const Index: Integer): PBlock;
  250. begin
  251.   if (Index >= Count) or (Index <= -1) then
  252.     raise EMemoryBuffer.CreateFmt(SListIndexError, [Index])
  253.   else
  254.     Result := FList[Index];
  255. end;
  256. procedure CheckError(ResultCode: Integer; const OP: string);
  257. var
  258.   ErrCode: Integer;
  259. begin
  260.   if ResultCode <> 0 then
  261.   begin
  262.     ErrCode := WSAGetLastError;
  263.     if (ErrCode <> WSAEWOULDBLOCK) or (ErrCode <> ERROR_IO_PENDING) then
  264.       raise ESocketError.CreateFmt(SWindowsSocketError,
  265.         [SysErrorMessage(ErrCode), ErrCode, Op]);
  266.   end;
  267. end;
  268. { TCustomSocket }
  269. constructor TCustomSocket.Create(ASocket: TSocket);
  270. begin
  271.   inherited Create;
  272.   FInitLock := False;
  273.   if WSAStartup($0202, WSData) <> 0 then
  274.     raise ESocketError.Create(SysErrorMessage(GetLastError));
  275.   FSocket := ASocket;
  276.   FActive := FSocket <> INVALID_SOCKET;
  277. end;
  278. destructor TCustomSocket.Destroy;
  279. begin
  280.   SetActive(False);
  281.   WSACleanup;
  282.   if FInitLock then
  283.     DeleteCriticalSection(FLock);
  284.   inherited Destroy;
  285. end;
  286. procedure TCustomSocket.Lock;
  287. begin
  288.   if not FInitLock then
  289.   begin
  290.     InitializeCriticalSection(FLock);
  291.     FInitLock := True;
  292.   end;
  293.   EnterCriticalSection(FLock);
  294. end;
  295. procedure TCustomSocket.UnLock;
  296. begin
  297.   if FInitLock then
  298.     LeaveCriticalSection(FLock);
  299. end;
  300. procedure TCustomSocket.Close;
  301. begin
  302.   SetActive(False);
  303. end;
  304. procedure TCustomSocket.Open;
  305. begin
  306.   SetActive(True);
  307. end;
  308. procedure TCustomSocket.DoRead(Data: Pointer; Count: Integer);
  309. begin
  310.   if Assigned(FOnRead) then
  311.     FOnRead(Self, Data, Count);
  312. end;
  313. procedure TCustomSocket.Error(ErrorEvent: TErrorEvent; var ErrCode: Integer);
  314. begin
  315.   if Assigned(FOnErrorEvent) then
  316.     FOnErrorEvent(Self, ErrorEvent, ErrCode);
  317. end;
  318. procedure TCustomSocket.Event(SocketEvent: TSocketEvent);
  319. begin
  320.   if Assigned(FOnEventEvent) then
  321.     FOnEventEvent(Self, SocketEvent);
  322. end;
  323. function TCustomSocket.GetRemoteAddress: string;
  324. var
  325.   SockAddrIn: TSockAddrIn;
  326.   Size: Integer;
  327. begin
  328.   Result := '';
  329.   if not FActive then Exit;
  330.   Size := SizeOf(SockAddrIn);
  331.   CheckError(getpeername(FSocket, SockAddrIn, Size), 'getpeername');
  332.   Result := inet_ntoa(SockAddrIn.sin_addr);
  333. end;
  334. function TCustomSocket.GetRemoteHost: string;
  335. var
  336.   SockAddrIn: TSockAddrIn;
  337.   Size: Integer;
  338.   HostEnt: PHostEnt;
  339. begin
  340.   Result := '';
  341.   if not FActive then Exit;
  342.   Size := SizeOf(SockAddrIn);
  343.   CheckError(getpeername(FSocket, SockAddrIn, Size), 'getpeername');
  344.   HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.s_addr, 4, PF_INET);
  345.   if HostEnt <> nil then Result := HostEnt.h_name;
  346. end;
  347. function TCustomSocket.Read(var Buf; Count: Integer): Integer;
  348. begin
  349.   raise ESocketError.Create('Error');
  350. end;
  351. function TCustomSocket.Write(var Buf; Count: Integer): Integer;
  352. begin
  353.   raise ESocketError.Create('Error');
  354. end;
  355. { TCustomerServerSocket }
  356. function TCustomerServerSocket.DoClientRead(ASocket: TCustomSocket;
  357.   AData: Pointer; ACount: Integer): Integer;
  358. begin
  359.   if not Assigned(FOnClientRead) then
  360.     Result := 0 else
  361.     Result := FOnClientRead(ASocket, AData, ACount);
  362. end;
  363. procedure TCustomerServerSocket.ClientSocketError(ASocket: TCustomSocket;
  364.   ErrorEvent: TErrorEvent; var ErrCode: Integer);
  365. begin
  366.   if Assigned(FOnClientError) then
  367.     FOnClientError(ASocket, ErrorEvent, ErrCode);
  368. end;
  369. procedure TCustomerServerSocket.ClientSocketEvent(ASocket: TCustomSocket;
  370.   SocketEvent: TSocketEvent);
  371. begin
  372.   if Assigned(FOnClientEvent) then
  373.     FOnClientEvent(ASocket, SocketEvent);
  374. end;
  375. { TServerSocket }
  376. procedure TServerSocket.Accept(ASocket: TSocket; ACompletionPort: THandle);
  377. var
  378.   Addr: TSockAddrIn;
  379.   AddrLen, Ret, ErrCode: Integer;
  380.   ClientWinSocket: TSocket;
  381.   ClientSocket: TServerClientSocket;
  382. begin
  383.   AddrLen := SizeOf(Addr);
  384.   ClientWinSocket := WinSock2.accept(ASocket, Addr, AddrLen);
  385.   if ClientWinSocket <> INVALID_SOCKET then
  386.   begin
  387.     if not Active and not IsAccept(ClientWinSocket) then
  388.     begin
  389.       closesocket(ClientWinSocket);
  390.       Exit;
  391.     end;
  392.     try
  393.       Event(seAccept);
  394.       ClientSocket := nil;
  395.       if Assigned(FOnGetSocket) then
  396.         FOnGetSocket(ClientWinSocket, ClientSocket);
  397.       if not Assigned(ClientSocket) then
  398.         ClientSocket := TServerClientSocket.Create(Self, ClientWinSocket);
  399.     except
  400.       closesocket(ClientWinSocket);
  401.       ErrCode := GetLastError;
  402.       Error(eeAccept, ErrCode);
  403.       Exit;
  404.     end;
  405.     Ret := CreateIoCompletionPort(ClientWinSocket, ACompletionPort, DWORD(ClientSocket), 0);
  406.     if Ret = 0 then
  407.       ClientSocket.Free;
  408.   end;
  409. end;
  410. constructor TServerSocket.Create;
  411. begin
  412.   inherited Create(INVALID_SOCKET);
  413.   FBuffer := TMemoryBuffer.Create(Self);
  414.   FClients := TList.Create;
  415.   FThreads := TList.Create;
  416.   FPort := 211;
  417.   FAcceptThread := nil;
  418.   FCompletionPort := 0;
  419.   IsMultiThread := True;
  420.   FHandle := Classes.AllocateHWnd(WndProc);
  421. end;
  422. destructor TServerSocket.Destroy;
  423. begin
  424.   SetActive(False);
  425.   FThreads.Free;
  426.   FClients.Free;
  427.   Classes.DeallocateHWnd(FHandle);
  428.   FBuffer.Free;
  429.   inherited Destroy;
  430. end;
  431. function TServerSocket.FindClientSocket(ASocket: TSocket): TCustomSocket;
  432. var
  433.   I: Integer;
  434. begin
  435.   Lock;
  436.   try
  437.     for I := 0 to FClients.Count - 1 do
  438.     begin
  439.       Result := FClients[I];
  440.       if ASocket = Result.SocketHandle then Exit;
  441.     end;
  442.     Result := nil;
  443.   finally
  444.     UnLock;
  445.   end;
  446. end;
  447. function TServerSocket.GetClientCount: Integer;
  448. begin
  449.   Result := FClients.Count;
  450. end;
  451. function TServerSocket.GetClients(const Index: Integer): TServerClientSocket;
  452. begin
  453.   Result := FClients[Index];
  454. end;
  455. procedure TServerSocket.InternalClose;
  456.   procedure CloseObject(var Handle: THandle);
  457.   begin
  458.     if Handle <> 0 then
  459.     begin
  460.       CloseHandle(Handle);
  461.       Handle := 0;
  462.     end;
  463.   end;
  464. var
  465.   I: Integer;
  466.   Thread: TThread;
  467. begin
  468.   Lock;
  469.   try
  470.     while FClients.Count > 0 do
  471.       TObject(FClients.Last).Free;
  472.     FClients.Clear;
  473.     for I := FThreads.Count - 1 downto 0 do
  474.     begin
  475.       Thread := FThreads[I];
  476.       PostQueuedCompletionStatus(FCompletionPort, 0, 0, Pointer(SHUTDOWN_FLAG));
  477.       Thread.Terminate;
  478.     end;
  479.     FThreads.Clear;
  480.     if FSocket <> INVALID_SOCKET then
  481.     begin
  482.       Event(seDisconnect);
  483.       closesocket(FSocket);
  484.       FSocket := INVALID_SOCKET;
  485.     end;
  486.     FAcceptThread.Terminate;
  487.     CloseObject(FCompletionPort);
  488.   finally
  489.     UnLock;
  490.   end;
  491. end;
  492. procedure TServerSocket.InternalOpen;
  493. var
  494.   I: Integer;
  495.   Thread: TThread;
  496.   SystemInfo: TSystemInfo;
  497. begin
  498.   Lock;
  499.   try
  500.     try
  501.       FCompletionPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
  502.       if FCompletionPort = 0 then
  503.         raise ESocketError.Create(SysErrorMessage(GetLastError));
  504.       Event(seInitIOPort);
  505.       GetSystemInfo(SystemInfo);
  506.       for I := 0 to SystemInfo.dwNumberOfProcessors * 2 - 1 do
  507.       begin
  508.         Thread := TWorkerThread.Create(Self);
  509.         FThreads.Add(Thread);
  510.       end;
  511.       FSocket := WSASocket(PF_INET, SOCK_STREAM, 0, nil, 0, WSA_FLAG_OVERLAPPED);
  512.       if FSocket = INVALID_SOCKET then
  513.         raise ESocketError.Create(SysErrorMessage(GetLastError));
  514.       Event(seInitSocket);
  515.       FillChar(FAddr, SizeOf(FAddr), 0);
  516.       FAddr.sin_family := AF_INET;
  517.       FAddr.sin_port := htons(FPort);
  518.       FAddr.sin_addr.S_addr := INADDR_ANY;
  519.       CheckError(bind(FSocket, @FAddr, SizeOf(FAddr)), 'bind');
  520.       Event(seListen);
  521.       CheckError(listen(FSocket, SOMAXCONN), 'listen');
  522.       FAcceptThread := TAcceptThread.Create(Self);  
  523.     except
  524.       InternalClose;
  525.       raise;
  526.     end;
  527.   finally
  528.     UnLock;
  529.   end;
  530. end;
  531. function TServerSocket.IsAccept(Socket: TSocket): Boolean;
  532. begin
  533.   Result := True;
  534. end;
  535. procedure TServerSocket.RegisterClient(ASocket: TCustomSocket);
  536. begin
  537.   Lock;
  538.   try
  539.     if FClients.IndexOf(ASocket) = -1 then
  540.     begin
  541.       FClients.Add(ASocket);
  542.       WSAAsyncSelect(ASocket.SocketHandle, FHandle, WM_CLIENTSOCKET, FD_CLOSE);
  543.     end;
  544.   finally
  545.     UnLock;
  546.   end;
  547. end;
  548. procedure TServerSocket.RemoveClient(ASocket: TCustomSocket);
  549. var
  550.   Index: Integer;
  551. begin
  552.   Lock;
  553.   try
  554.     Index := FClients.IndexOf(ASOcket);
  555.     if Index <> -1 then
  556.       FClients.Delete(Index);
  557.   finally
  558.     UnLock;
  559.   end;
  560. end;
  561. procedure TServerSocket.SetActive(Value: Boolean);
  562. begin
  563.   if FActive = Value then Exit;
  564.   if Value then
  565.     InternalOpen
  566.   else
  567.     InternalClose;
  568.   FActive := Value;
  569. end;
  570. procedure TServerSocket.SetPort(Value: Integer);
  571. begin
  572.   if Active then
  573.     raise ESocketError.Create('Cann''t change port');
  574.   FPort := Value;
  575. end;
  576. procedure TServerSocket.WMClientClose(var Message: TCMSocketMessage);
  577. var
  578.   ClientSocket: TCustomSocket;
  579. begin
  580.   ClientSocket := FindClientSocket(Message.Socket);
  581.   if Assigned(ClientSocket) then
  582.     ClientSocket.Free;
  583. end;
  584. procedure TServerSocket.WndProc(var Message: TMessage);
  585. begin
  586.   try
  587.     Dispatch(Message);
  588.   except
  589.     if Assigned(ApplicationHandleException) then
  590.       ApplicationHandleException(Self);
  591.   end;
  592. end;
  593. { TServerClientSocket }
  594. constructor TServerClientSocket.Create(AServerSocket: TServerSocket;
  595.   ASocket: TSocket);
  596. begin
  597.   inherited Create(ASocket);
  598.   FServerSocket := AServerSocket;
  599.   FBuffer := FServerSocket.FBuffer;
  600.   FBlock := TList.Create;
  601.   FServerSocket.RegisterClient(Self);
  602.   FOnRead := FServerSocket.OnClientRead;
  603.   OnErrorEvent := FServerSocket.ClientSocketError;
  604.   OnEventEvent := FServerSocket.ClientSocketEvent;
  605.   PrepareRecv;
  606.   Event(seConnect);
  607. end;
  608. destructor TServerClientSocket.Destroy;
  609. var
  610.   I: Integer;
  611. begin
  612.   FServerSocket.RemoveClient(Self);
  613.   for I := FBlock.Count - 1 downto 0 do
  614.     FBuffer.RemoveBlock(FBlock[I]);
  615.   FBlock.Free;
  616.   inherited Destroy;
  617. end;
  618. procedure TServerClientSocket.SetActive(Value: Boolean);
  619. var
  620.   Linger: TLinger;
  621. begin
  622.   if FActive = Value then Exit;
  623.   if not Value then
  624.   begin
  625.     if FSocket <> INVALID_SOCKET then
  626.     begin
  627.       Event(seDisconnect);
  628.       FillChar(Linger, SizeOf(Linger), 0);
  629.       setsockopt(FSocket, SOL_SOCKET, SO_LINGER, @Linger, Sizeof(Linger));
  630.       closesocket(FSocket);
  631.       FSocket := INVALID_SOCKET;
  632.     end;
  633.   end else
  634.     raise ESocketError.Create('当前socket不支持连接操作');
  635.   FActive := Value;
  636. end; 
  637. function TServerClientSocket.AllocBlock: PBlock;
  638. var
  639.   I: Integer;
  640. begin
  641.   for I := 0 to FBlock.Count - 1 do
  642.   begin
  643.     Result := FBlock[I];
  644.     if not Result.Data.IsUse then
  645.     begin
  646.       Result.Data.IsUse := True;
  647.       Exit;
  648.     end;
  649.   end;
  650.   Result := FBuffer.AllocBlock;
  651.   FBlock.Add(Result);
  652.   Result.Data.IsUse := True;
  653. end;
  654. function TServerClientSocket.Read(var Buf; Count: Integer): Integer;
  655. begin
  656.   { 读操作由DoReceive触发OnRead进行读 }
  657.   raise ESocketError.Create('读操作错误');
  658. end;
  659. function TServerClientSocket.Write(var Buf; Count: Integer): Integer;
  660. var
  661.   Block: PBlock;
  662.   ErrCode: Integer;
  663.   Flags, BytesSend: Cardinal;  
  664. begin
  665.   Result := Count;
  666.   if Result = 0 then Exit;
  667.   Block := AllocBlock;
  668.   with Block^.Data do
  669.   begin
  670.     Flags := 0;
  671.     Event := seWrite;
  672.     wsaBuffer.buf := @Buf;
  673.     wsaBuffer.len := Result;
  674.     if SOCKET_ERROR = WSASend(FSocket, @wsaBuffer, 1, BytesSend, Flags, @Overlapped, nil) then
  675.     begin
  676.       ErrCode := WSAGetLastError;
  677.       if ErrCode <> ERROR_IO_PENDING then
  678.       begin
  679.         Result := SOCKET_ERROR;
  680.         Error(eeSend, ErrCode);
  681.       end;
  682.     end;
  683.   end;
  684. end;
  685. function TServerClientSocket.PrepareRecv(Block: PBlock = nil): Boolean;
  686. var
  687.   ErrCode: Integer;
  688.   Flags, Transfer: Cardinal;
  689. begin
  690.   if not Assigned(Block) then
  691.     Block := AllocBlock;
  692.   with Block^.Data do
  693.   begin
  694.     Flags := 0;
  695.     Event := seRead;
  696.     FillChar(Buffer, SizeOf(Buffer), 0);
  697.     FillChar(Overlapped, SizeOf(Overlapped), 0);
  698.     wsaBuffer.buf := Buffer;
  699.     wsaBuffer.len := MAX_BUFSIZE;
  700.     Result := SOCKET_ERROR <> WSARecv(FSocket, @wsaBuffer, 1, Transfer, Flags, @Overlapped, nil);
  701.     if not Result then
  702.     begin
  703.       ErrCode := WSAGetLastError;
  704.       Result := ErrCode = ERROR_IO_PENDING;
  705.       if not Result then
  706.       begin
  707.         Block.Data.IsUse := False;
  708.         Error(eeReceive, ErrCode);
  709.       end;
  710.     end;
  711.   end;
  712. end;
  713. const
  714.   RESPONSE_UNKNOWN = $0001;
  715.   RESPONSE_SUCCESS = $0002;
  716.   RESPONSE_FAIL = $FFFF;
  717.   
  718. function TServerClientSocket.WorkBlock(var Block: PBlock; Transfered: DWORD): DWORD;
  719. var
  720.   ErrCode: Integer;
  721.   Flag, BytesSend: Cardinal;
  722. begin
  723.   Result := RESPONSE_SUCCESS;
  724.   with Block^.Data do
  725.   try
  726.     case Block^.Data.Event of
  727.       seRead:
  728.       begin
  729.         Self.Event(seRead);
  730.         DoRead(@Buffer, Transfered);
  731.         if not PrepareRecv(Block) then
  732.           Result := RESPONSE_FAIL;
  733.       end;
  734.       seWrite:
  735.       begin
  736.         Self.Event(seWrite);
  737.         Dec(wsaBuffer.len, Transfered);
  738.         if wsaBuffer.len <= 0 then
  739.         begin
  740.           { 发送完成,将Block置空,返回到FBlock的可使用的缓区中 }
  741.           Block.Data.IsUse := False;
  742.           Block := nil;
  743.         end else
  744.         begin
  745.           { 数据还没发送完成,继续发送 }
  746.           Flag := 0;
  747.           Inc(wsaBuffer.buf, Transfered);
  748.           FillChar(Overlapped, SizeOf(Overlapped), 0);
  749.           if SOCKET_ERROR = WSASend(FSocket, @wsaBuffer, 1, BytesSend,
  750.             Flag, @Overlapped, nil) then
  751.           begin
  752.             ErrCode := WSAGetLastError;
  753.             if ErrCode <> ERROR_IO_PENDING then
  754.               Error(eeSend, ErrCode);
  755.           end;
  756.         end;
  757.       end;
  758.     end;
  759.   except
  760.     Result := RESPONSE_FAIL;
  761.   end;
  762. end;
  763. { TSocketThread }
  764. constructor TSocketThread.Create(AServer: TServerSocket);
  765. begin
  766.   FServer := AServer;
  767.   inherited Create(False);
  768.   FreeOnTerminate := True;
  769. end;
  770. { TAcceptThread }
  771. procedure TAcceptThread.Execute;
  772. begin
  773.   with FServer do
  774.     while not Terminated and Active do
  775.       Accept(SocketHandle, CompletionPort);
  776. end;
  777. { TWorkerThread }
  778. procedure TWorkerThread.Execute;
  779. var
  780.   Block: PBlock;
  781.   Transfered: DWORD;
  782.   ClientSocket: TServerClientSocket;
  783. begin
  784.   while FServer.Active do
  785.   begin
  786.     Block := nil;
  787.     Transfered := 0;
  788.     ClientSocket := nil;
  789.     if not GetQueuedCompletionStatus(FServer.CompletionPort, Transfered,
  790.       DWORD(ClientSocket), POverlapped(Block), INFINITE) then
  791.     begin
  792.       if Assigned(ClientSocket) then
  793.         FreeAndNil(ClientSocket);
  794.       Continue;
  795.     end;
  796.     { 客户可能超时?? 或是断开连接,I/O失败 }
  797.     if Transfered = 0 then
  798.     begin
  799.       FreeAndNil(ClientSocket);
  800.       Continue;
  801.     end;
  802.     { 通知结束 }
  803.     if Cardinal(Block) = SHUTDOWN_FLAG then
  804.       break;
  805.     if not FServer.Active then break;
  806.     case ClientSocket.WorkBlock(Block, Transfered) of
  807.       RESPONSE_UNKNOWN:
  808.         { 操作未知的话,应该返回给客户端:...不应该Close....保留 }
  809.         FreeAndNil(ClientSocket);
  810.       RESPONSE_FAIL:
  811.         FreeAndNil(ClientSocket);
  812.     end;
  813.   end;
  814. end;
  815. end.