WSockets.pas
上传用户:hndmjx
上传日期:2014-09-16
资源大小:3369k
文件大小:32k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit WSockets;
  2. interface
  3. uses
  4.   Windows, WinSock, CommandsAndUtils, Classes, Messages;
  5. const
  6.   WM_ASYNCSELECT = WM_USER + 1;
  7.   READ_BUFFER_SIZE = 1024;
  8.   MAX_LOOP = 100;
  9. type
  10.   TSocketState = (ssNotStarted, ssClosed, ssConnected, ssListening, ssOpen);
  11.   TOnError = procedure(Sender: TObject; Error: integer; Msg: string) of object;
  12.   TOnData = procedure(Sender: TObject; Socket: TSocket) of object;
  13.   TOnAccept = procedure(Sender: TObject; Socket: TSocket) of object;
  14.   TOnConnect = procedure(Sender: TObject; Socket: TSocket) of object;
  15.   TOnClose = procedure(Sender: TObject; Socket: TSocket) of object;
  16.   TReadBuffer = array[1..READ_BUFFER_SIZE] of byte;
  17.   TClientList = class(TObject)
  18.   private
  19.     FSockets: TList;
  20.   protected
  21.     function GetSockets(Index: integer): TSocket;
  22.     function GetCount: integer;
  23.   public
  24.     constructor Create;
  25.     destructor Destroy; override;
  26.     function Add(Socket: TSocket): boolean;
  27.     procedure Delete(Socket: TSocket);
  28.     procedure Clear;
  29.     function IndexOf(Socket: TSocket): integer;
  30.     property Sockets[Index: integer]: TSocket read GetSockets; default;
  31.     property Count: integer read GetCount;
  32.   end;
  33.   TCustomWSocket = class(TComponent)
  34.   private
  35.     {WinSocket Information Private Fields}
  36.     FVersion: string;
  37.     FDescription: string;
  38.     FSystemStatus: string;
  39.     FMaxSockets: integer;
  40.     FMaxUDPSize: integer;
  41.     {End WinSocket Information Private Fields}
  42.     FProtocol: integer;
  43.     FType: integer;
  44.     FReadBuffer: TReadBuffer;
  45.     FLocalSocket: TSocket;
  46.     FSocketState: TSocketState;
  47.     FLastError: integer;
  48.     FOnError: TOnError;
  49.   protected
  50.     procedure SocketError(Error: integer);
  51.     function LastErrorDesc: string;
  52.     function GetLocalHostAddress: string;
  53.     function GetLocalHostName: string;
  54.     {Socket Helper Functions}
  55.     procedure SocketClose(var Socket: TSocket; Handle: HWND);
  56.     function SocketQueueSize(Socket: TSocket): longint;
  57.     procedure SocketWrite(Socket: TSocket; Flag: integer; Data: string);
  58.     function SocketRead(Socket: TSocket; Flag: integer): string;
  59.     function SocketWriteBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  60.     function SocketReadBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  61.     procedure SocketWriteTo(Socket: TSocket; Flag: integer; Data: string; var SockAddrIn: TSockAddrIn);
  62.     function SocketReadFrom(Socket: TSocket; Flag: integer; var SockAddrIn: TSockAddrIn): string;
  63.     function SocketWriteBufferTo(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  64.     function SocketReadBufferFrom(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  65.   public
  66.     constructor Create(AOwner: TComponent); override;
  67.     destructor Destroy; override;
  68.     {Address and Port Resolving Helper Functions}
  69.     function GetSockAddrIn(Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
  70.     function GetAnySockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
  71.     function GetBroadcastSockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
  72.     function SockAddrInToName(SockAddrIn: TSockAddrIn): string;
  73.     function SockAddrInToAddress(SockAddrIn: TSockAddrIn): string;
  74.     function SockAddrInToPort(SockAddrIn: TSockAddrIn): string;
  75.     function SocketToName(Socket: TSocket): string;
  76.     function SocketToAddress(Socket: TSocket): string;
  77.     function SocketToPort(Socket: TSocket): string;
  78.     function PeerToName(Socket: TSocket): string;
  79.     function PeerToAddress(Socket: TSocket): string;
  80.     function PeerToPort(Socket: TSocket): string;
  81.     {WinSocket Information Properties}
  82.     property Version: string read FVersion;
  83.     property Description: string read FDescription;
  84.     property SystemStatus: string read FSystemStatus;
  85.     property MaxSockets: integer read FMaxSockets;
  86.     property MaxUDPSize: integer read FMaxUDPSize;
  87.     {End WinSocket Information Properties}
  88.     property LocalSocket: TSocket read FLocalSocket;
  89.     property SocketState: TSocketState read FSocketState;
  90.     property LastError: integer read FLastError;
  91.     property LocalHostAddress: string read GetLocalHostAddress;
  92.     property LocalHostName: string read GetLocalHostName;
  93.   published
  94.     property OnError: TOnError read FOnError write FOnError;
  95.   end;
  96.   TTCPClient = class(TCustomWSocket)
  97.   private
  98.     FHandle: HWND;
  99.     FHost: string;
  100.     FPort: string;
  101.     FOnData: TOnData;
  102.     FOnConnect: TOnConnect;
  103.     FOnClose: TOnClose;
  104.   protected
  105.     procedure WndProc(var AMsg: TMessage);
  106.     procedure OpenConnection(Socket: TSocket; Error: word);
  107.     procedure IncommingData(Socket: TSocket; Error: word);
  108.     procedure CloseConnection(Socket: TSocket; Error: word);
  109.     function GetPeerAddress: string;
  110.     function GetPeerPort: string;
  111.   public
  112.     constructor Create(AOwner: TComponent); override;
  113.     destructor Destroy; override;
  114.     procedure Open;
  115.     procedure Close;
  116.     function Peek: string;
  117.     procedure Write(Data: string);
  118.     function Read: string;
  119.     function WriteBuffer(Buffer: Pointer; Size: integer): integer;
  120.     function ReadBuffer(Buffer: Pointer; Size: integer): integer;
  121.     property Handle: HWND read FHandle;
  122.     property PeerAddress: string read GetPeerAddress;
  123.     property PeerPort: string read GetPeerPort;
  124.   published
  125.     property Host: string read FHost write FHost;
  126.     property Port: string read FPort write FPort;
  127.     property OnData: TOnData read FOnData write FOnData;
  128.     property OnConnect: TOnConnect read FOnConnect write FOnConnect;
  129.     property OnClose: TOnClose read FOnClose write FOnClose;
  130.   end;
  131.   TTCPServer = class(TCustomWSocket)
  132.   private
  133.     FHandle: HWND;
  134.     FPort: string;
  135.     FOnData: TOnData;
  136.     FOnAccept: TOnAccept;
  137.     FOnClose: TOnClose;
  138.     FClients: TClientList;
  139.   protected
  140.     procedure WndProc(var AMsg: TMessage);
  141.     procedure OpenConnection(Socket: TSocket; Error: word);
  142.     procedure IncommingData(Socket: TSocket; Error: word);
  143.     procedure CloseConnection(Socket: TSocket; Error: word);
  144.   public
  145.     constructor Create(AOwner: TComponent); override;
  146.     destructor Destroy; override;
  147.     procedure Open;
  148.     procedure Close;
  149.     function Peek(Socket: TSocket): string;
  150.     procedure Write(Socket: TSocket; Data: string);
  151.     function Read(Socket: TSocket): string;
  152.     function WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  153.     function ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  154.     procedure Disconnect(Socket: TSocket);
  155.     property Handle: HWND read FHandle;
  156.     property Clients: TClientList read FClients;
  157.   published
  158.     property Port: string read FPort write FPort;
  159.     property OnData: TOnData read FOnData write FOnData;
  160.     property OnAccept: TOnAccept read FOnAccept write FOnAccept;
  161.     property OnClose: TOnClose read FOnClose write FOnClose;
  162.   end;
  163. procedure Register;
  164. implementation
  165. procedure Register;
  166. begin
  167.   RegisterComponents('Samples', [TTCPClient, TTCPServer]);
  168. end;
  169. (**** TClientList Class ****)
  170. constructor TClientList.Create;
  171. begin
  172.   inherited Create;
  173.   FSockets:= TList.Create;
  174. end;
  175. destructor TClientList.Destroy;
  176. begin
  177.   Clear;
  178.   FSockets.Free;
  179.   inherited Destroy;
  180. end;
  181. function TClientList.GetSockets(Index: integer): TSocket;
  182. begin
  183.   Result:= TSocket(FSockets[Index]);
  184. end;
  185. function TClientList.GetCount: integer;
  186. begin
  187.   Result:= FSockets.Count;
  188. end;
  189. function TClientList.Add(Socket: TSocket): boolean;
  190. begin
  191.   Result:= (FSockets.Add(Ptr(Socket)) >= 0);
  192. end;
  193. procedure TClientList.Delete(Socket: TSocket);
  194. var
  195.   i: integer;
  196. begin
  197.   for i:= 0 to FSockets.Count-1 do
  198.     begin
  199.       if TSocket(FSockets[i]) = Socket then
  200.         begin
  201.           FSockets.Delete(i);
  202.           Break;
  203.         end;
  204.     end;
  205. end;
  206. procedure TClientList.Clear;
  207. begin
  208.   FSockets.Clear;
  209. end;
  210. function TClientList.IndexOf(Socket: TSocket): integer;
  211. var
  212.   i: integer;
  213. begin
  214.   Result:= -1;
  215.   for i:= 0 to FSockets.Count-1 do
  216.     begin
  217.       if TSocket(FSockets[i]) = Socket then
  218.         begin
  219.           Result:= i;
  220.           Break;
  221.         end;
  222.     end;
  223. end;
  224. (**** TCustomWSocket Class ****)
  225. constructor TCustomWSocket.Create(AOwner: TComponent);
  226. var
  227.   WSAData: TWSAData;
  228. begin
  229.   inherited Create(AOwner);
  230.   FProtocol:= IPPROTO_IP;
  231.   FType:= SOCK_RAW;
  232.   FLocalSocket:= INVALID_SOCKET;
  233.   FSocketState:= ssNotStarted;
  234.   FLastError:= WSAStartup($101, WSAData);
  235.   if FLastError = 0 then
  236.     begin
  237.       FSocketState:= ssClosed;
  238.       with WSAData do
  239.         begin
  240.           FVersion:= Concat(IntToStr(Hi(wVersion)),'.',(IntToStr(Lo(wVersion))));
  241.           FDescription:= StrPas(szDescription);
  242.          FSystemStatus:= StrPas(szSystemStatus);
  243.           FMaxSockets:= iMaxSockets;
  244.           FMaxUDPSize:= iMaxUDPDg;
  245.         end;
  246.     end
  247.   else
  248.     SocketError(FLastError);
  249. end;
  250. destructor TCustomWSocket.Destroy;
  251. begin
  252.   if FLocalSocket <> INVALID_SOCKET then
  253.     closesocket(FLocalSocket);
  254.   if FSocketState <> ssNotStarted then
  255.     if WSACleanUp = SOCKET_ERROR then
  256.       SocketError(WSAGetLastError);
  257.   inherited Destroy;
  258. end;
  259. function TCustomWSocket.GetSockAddrIn(
  260.          Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
  261. var
  262.   ProtoEnt: PProtoEnt;
  263.   ServEnt: PServEnt;
  264.   HostEnt: PHostEnt;
  265. begin
  266.   Result:= false;
  267.   SockAddrIn.sin_family:= AF_INET;
  268.   ProtoEnt:= getprotobynumber(FProtocol);
  269.   if ProtoEnt = nil then
  270.     begin
  271.       SocketError(WSAGetLastError);
  272.       Exit;
  273.     end;
  274.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  275.   if ServEnt = nil then
  276.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  277.   else
  278.     SockAddrIn.sin_port:= ServEnt^.s_port;
  279.   SockAddrIn.sin_addr.s_addr:= inet_addr(PChar(Host));
  280.   if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
  281.     begin
  282.       HostEnt:= gethostbyname(PChar(Host));
  283.       if HostEnt = nil then
  284.         begin
  285.          SocketError(WSAGetLastError);
  286.          Exit;
  287.         end;
  288.       SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^);
  289.     end;
  290.   Result:= true;
  291. end;
  292. function TCustomWSocket.GetAnySockAddrIn(
  293.          Port: string; var SockAddrIn: TSockAddrIn): boolean;
  294. var
  295.   ProtoEnt: PProtoEnt;
  296.   ServEnt: PServEnt;
  297. begin
  298.   Result:= false;
  299.   SockAddrIn.sin_family:= AF_INET;
  300.   ProtoEnt:= getprotobynumber(FProtocol);
  301.   if ProtoEnt = nil then
  302.     Exit;
  303.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  304.   if ServEnt = nil then
  305.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  306.   else
  307.     SockAddrIn.sin_port:= ServEnt^.s_port;
  308.   SockAddrIn.sin_addr.s_addr:= INADDR_ANY;
  309.   Result:= true;
  310. end;
  311. function TCustomWSocket.GetBroadcastSockAddrIn(
  312.          Port: string; var SockAddrIn: TSockAddrIn): boolean;
  313. var
  314.   ProtoEnt: PProtoEnt;
  315.   ServEnt: PServEnt;
  316. begin
  317.   Result:= false;
  318.   SockAddrIn.sin_family:= AF_INET;
  319.   ProtoEnt:= getprotobynumber(FProtocol);
  320.   if ProtoEnt = nil then
  321.     Exit;
  322.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  323.   if ServEnt = nil then
  324.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  325.   else
  326.     SockAddrIn.sin_port:= ServEnt^.s_port;
  327.   SockAddrIn.sin_addr.s_addr:= INADDR_BROADCAST;
  328.   Result:= true;
  329. end;
  330. function TCustomWSocket.SockAddrInToName(SockAddrIn: TSockAddrIn): string;
  331. var
  332.   HostEnt: PHostEnt;
  333. begin
  334.   HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  335.   if HostEnt <> nil then
  336.     Result:= HostEnt.h_name;
  337. end;
  338. function TCustomWSocket.SockAddrInToAddress(SockAddrIn: TSockAddrIn): string;
  339. begin
  340.   Result:= inet_ntoa(SockAddrIn.sin_addr);
  341. end;
  342. function TCustomWSocket.SockAddrInToPort(SockAddrIn: TSockAddrIn): string;
  343. begin
  344.   Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  345. end;
  346. function TCustomWSocket.SocketToName(Socket: TSocket): string;
  347. var
  348.   SockAddrIn: TSockAddrIn;
  349.   Len: integer;
  350.   HostEnt: PHostEnt;
  351. begin
  352.   if Socket <> INVALID_SOCKET then
  353.     begin
  354.       Len:= SizeOf(SockAddrIn);
  355.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  356.         begin
  357.           HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  358.           if HostEnt <> nil then
  359.             Result:= HostEnt.h_name;
  360.         end;
  361.     end;
  362. end;
  363. function TCustomWSocket.SocketToAddress(Socket: TSocket): string;
  364. var
  365.   SockAddrIn: TSockAddrIn;
  366.   Len: integer;
  367. begin
  368.   if Socket <> INVALID_SOCKET then
  369.     begin
  370.       Len:= SizeOf(SockAddrIn);
  371.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  372.         Result:= inet_ntoa(SockAddrIn.sin_addr);
  373.     end;
  374. end;
  375. function TCustomWSocket.SocketToPort(Socket: TSocket): string;
  376. var
  377.   SockAddrIn: TSockAddrIn;
  378.   Len: integer;
  379. begin
  380.   if Socket <> INVALID_SOCKET then
  381.     begin
  382.       Len:= SizeOf(SockAddrIn);
  383.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  384.         Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  385.     end;
  386. end;
  387. function TCustomWSocket.PeerToName(Socket: TSocket): string;
  388. var
  389.   SockAddrIn: TSockAddrIn;
  390.   Len: integer;
  391.   HostEnt: PHostEnt;
  392. begin
  393.   if Socket <> INVALID_SOCKET then
  394.     begin
  395.       Len:= SizeOf(SockAddrIn);
  396.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  397.         begin
  398.           HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  399.           if HostEnt <> nil then
  400.             Result:= HostEnt.h_name;
  401.         end;
  402.     end;
  403. end;
  404. function TCustomWSocket.PeerToAddress(Socket: TSocket): string;
  405. var
  406.   SockAddrIn: TSockAddrIn;
  407.   Len: integer;
  408. begin
  409.   if Socket <> INVALID_SOCKET then
  410.     begin
  411.       Len:= SizeOf(SockAddrIn);
  412.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  413.         Result:= inet_ntoa(SockAddrIn.sin_addr);
  414.     end;
  415. end;
  416. function TCustomWSocket.PeerToPort(Socket: TSocket): string;
  417. var
  418.   SockAddrIn: TSockAddrIn;
  419.   Len: integer;
  420. begin
  421.   if Socket <> INVALID_SOCKET then
  422.     begin
  423.       Len:= SizeOf(SockAddrIn);
  424.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  425.         Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  426.     end;
  427. end;
  428. procedure TCustomWSocket.SocketClose(var Socket: TSocket; Handle: HWND);
  429. var
  430.   RC: integer;
  431. begin
  432.   if Socket <> INVALID_SOCKET then
  433.     begin
  434.       if WSAASyncSelect(Socket, Handle, WM_ASYNCSELECT, 0) <> 0 then
  435.         begin
  436.           SocketError(WSAGetLastError);
  437.           Exit;
  438.         end;
  439.       if shutdown(Socket, 1) <> 0 then
  440.         if WSAGetLastError <> WSAENOTCONN then
  441.           begin
  442.             SocketError(WSAGetLastError);
  443.             Exit;
  444.           end;
  445.       repeat
  446.         RC:= recv(Socket, FReadBuffer, SizeOf(TReadBuffer), 0);
  447.       until (RC = 0) or (RC = SOCKET_ERROR);
  448.       if closesocket(Socket) <> 0 then
  449.         SocketError(WSAGetLastError)
  450.       else
  451.         Socket:= INVALID_SOCKET;
  452.     end;
  453. end;
  454. function TCustomWSocket.SocketQueueSize(Socket: TSocket): longint;
  455. var
  456.   Size: longint;
  457. begin
  458.   Result:= 0;
  459.   if ioctlsocket(Socket, FIONREAD, Size) <> 0 then
  460.     SocketError(WSAGetLastError)
  461.   else
  462.     Result:= Size;
  463. end;
  464. procedure TCustomWSocket.SocketWrite(Socket: TSocket; Flag: integer; Data: string);
  465. var
  466.   TotSent, ToSend, Sent, ErrorLoop: integer;
  467. begin
  468.   if Data <> '' then
  469.     begin
  470.       ErrorLoop:= 0;
  471.       TotSent:= 0;
  472.       ToSend:= Length(Data);
  473.       repeat
  474.         Sent:= send(Socket, Data[TotSent+1], (ToSend-TotSent), Flag);
  475.         if Sent = SOCKET_ERROR then
  476.           begin
  477.             Inc(ErrorLoop);
  478.             if WSAGetLastError <> WSAEWOULDBLOCK then
  479.               begin
  480.                 SocketError(WSAGetLastError);
  481.                 Exit;
  482.               end;
  483.           end
  484.         else
  485.           Inc(TotSent, Sent);
  486.       until (TotSent >= ToSend) or (ErrorLoop > MAX_LOOP);
  487.     end;
  488. end;
  489. function TCustomWSocket.SocketRead(Socket: TSocket; Flag: integer): string;
  490. var
  491.   Received: longint;
  492. begin
  493.   Result:= '';
  494.   Received:= recv(Socket, FReadBuffer, SizeOf(TReadBuffer), Flag);
  495.   if Received = SOCKET_ERROR then
  496.     begin
  497.       if WSAGetLastError <> WSAEWOULDBLOCK then
  498.         SocketError(WSAGetLastError);
  499.     end
  500.   else
  501.     begin
  502.       SetLength(Result, Received);
  503.       Move(FReadBuffer, Result[1], Received);
  504.     end;
  505. end;
  506. function TCustomWSocket.SocketWriteBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  507. begin
  508.   Result:= send(Socket, Buffer^, Size, Flag);
  509.   if Result = SOCKET_ERROR then
  510.     begin
  511.       Result:= 0;
  512.       if WSAGetLastError <> WSAEWOULDBLOCK then
  513.         SocketError(WSAGetLastError);
  514.     end;
  515. end;
  516. function TCustomWSocket.SocketReadBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  517. begin
  518.   Result:= recv(Socket, Buffer^, Size, Flag);
  519.   if Result = SOCKET_ERROR then
  520.     begin
  521.       Result:= 0;
  522.       if WSAGetLastError <> WSAEWOULDBLOCK then
  523.         SocketError(WSAGetLastError);
  524.     end;
  525. end;
  526. procedure TCustomWSocket.SocketWriteTo(Socket: TSocket; Flag: integer; Data: string; var SockAddrIn: TSockAddrIn);
  527. var
  528.   TotSent, ToSend, Sent, ErrorLoop: integer;
  529. begin
  530.   if Data <> '' then
  531.     begin
  532.       ErrorLoop:= 0;
  533.       TotSent:= 0;
  534.       ToSend:= Length(Data);
  535.       repeat
  536.         Sent:= sendto(Socket, Data[TotSent+1], (ToSend-TotSent), Flag, SockAddrIn, SizeOf(SockAddrIn));
  537.         if Sent = SOCKET_ERROR then
  538.           begin
  539.             Inc(ErrorLoop);
  540.             if WSAGetLastError <> WSAEWOULDBLOCK then
  541.               begin
  542.                 SocketError(WSAGetLastError);
  543.                 Exit;
  544.               end;
  545.           end
  546.         else
  547.           Inc(TotSent, Sent);
  548.       until (TotSent >= ToSend) or (ErrorLoop > MAX_LOOP);
  549.     end;
  550. end;
  551. function TCustomWSocket.SocketReadFrom(Socket: TSocket; Flag: integer; var SockAddrIn: TSockAddrIn): string;
  552. var
  553.   Len: integer;
  554.   Received: longint;
  555. begin
  556.   Len:= SizeOf(SockAddrIn);
  557.   Received:= recvfrom(Socket, FReadBuffer, SizeOf(TReadBuffer), Flag, SockAddrIn, Len);
  558.   if Received = SOCKET_ERROR then
  559.     begin
  560.       if WSAGetLastError <> WSAEWOULDBLOCK then
  561.         SocketError(WSAGetLastError);
  562.     end
  563.   else
  564.     begin
  565.       SetLength(Result, Received);
  566.       Move(FReadBuffer, Result[1], Received);
  567.     end;
  568. end;
  569. function TCustomWSocket.SocketWriteBufferTo(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  570. begin
  571.   Result:= sendto(Socket, Buffer^, Size, Flag, SockAddrIn, SizeOf(SockAddrIn));
  572.   if Result = SOCKET_ERROR then
  573.     begin
  574.       Result:= 0;
  575.       if WSAGetLastError <> WSAEWOULDBLOCK then
  576.         SocketError(WSAGetLastError);
  577.     end;
  578. end;
  579. function TCustomWSocket.SocketReadBufferFrom(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  580. var
  581.   Len: integer;
  582. begin
  583.   Len:= SizeOf(SockAddrIn);
  584.   Result:= recvfrom(Socket, Buffer^, Size, Flag, SockAddrIn, Len);
  585.   if Result = SOCKET_ERROR then
  586.     begin
  587.       Result:= 0;
  588.       if WSAGetLastError <> WSAEWOULDBLOCK then
  589.         SocketError(WSAGetLastError);
  590.     end;
  591. end;
  592. procedure TCustomWSocket.SocketError(Error: integer);
  593. begin
  594.   FLastError:= Error;
  595.   if Assigned(FOnError) then
  596.     FOnError(Self, FLastError, LastErrorDesc);
  597. end;
  598. function TCustomWSocket.LastErrorDesc: string;
  599. begin
  600.   case FLastError of
  601.     WSAEINTR           : Result:= 'Interrupted system call';
  602.     WSAEBADF           : Result:= 'Bad file number';
  603.     WSAEACCES          : Result:= 'Permission denied';
  604.     WSAEFAULT          : Result:= 'Bad address';
  605.     WSAEINVAL          : Result:= 'Invalid argument';
  606.     WSAEMFILE          : Result:= 'Too many open files';
  607.     WSAEWOULDBLOCK     : Result:= 'Operation would block';
  608.     WSAEINPROGRESS     : Result:= 'Operation now in progress';
  609.     WSAEALREADY        : Result:= 'Operation already in progress';
  610.     WSAENOTSOCK        : Result:= 'Socket operation on nonsocket';
  611.     WSAEDESTADDRREQ    : Result:= 'Destination address required';
  612.     WSAEMSGSIZE        : Result:= 'Message too long';
  613.     WSAEPROTOTYPE      : Result:= 'Protocol wrong type for socket';
  614.     WSAENOPROTOOPT     : Result:= 'Protocol not available';
  615.     WSAEPROTONOSUPPORT : Result:= 'Protocol not supported';
  616.     WSAESOCKTNOSUPPORT : Result:= 'Socket not supported';
  617.     WSAEOPNOTSUPP      : Result:= 'Operation not supported on socket';
  618.     WSAEPFNOSUPPORT    : Result:= 'Protocol family not supported';
  619.     WSAEAFNOSUPPORT    : Result:= 'Address family not supported';
  620.     WSAEADDRINUSE      : Result:= 'Address already in use';
  621.     WSAEADDRNOTAVAIL   : Result:= 'Can''t assign requested address';
  622.     WSAENETDOWN        : Result:= 'Network is down';
  623.     WSAENETUNREACH     : Result:= 'Network is unreachable';
  624.     WSAENETRESET       : Result:= 'Network dropped connection on reset';
  625.     WSAECONNABORTED    : Result:= 'Software caused connection abort';
  626.     WSAECONNRESET      : Result:= 'Connection reset by peer';
  627.     WSAENOBUFS         : Result:= 'No buffer space available';
  628.     WSAEISCONN         : Result:= 'Socket is already connected';
  629.     WSAENOTCONN        : Result:= 'Socket is not connected';
  630.     WSAESHUTDOWN       : Result:= 'Can''t send after socket shutdown';
  631.     WSAETOOMANYREFS    : Result:= 'Too many references:can''t splice';
  632.     WSAETIMEDOUT       : Result:= 'Connection timed out';
  633.     WSAECONNREFUSED    : Result:= 'Connection refused';
  634.     WSAELOOP           : Result:= 'Too many levels of symbolic links';
  635.     WSAENAMETOOLONG    : Result:= 'File name is too long';
  636.     WSAEHOSTDOWN       : Result:= 'Host is down';
  637.     WSAEHOSTUNREACH    : Result:= 'No route to host';
  638.     WSAENOTEMPTY       : Result:= 'Directory is not empty';
  639.     WSAEPROCLIM        : Result:= 'Too many processes';
  640.     WSAEUSERS          : Result:= 'Too many users';
  641.     WSAEDQUOT          : Result:= 'Disk quota exceeded';
  642.     WSAESTALE          : Result:= 'Stale NFS file handle';
  643.     WSAEREMOTE         : Result:= 'Too many levels of remote in path';
  644.     WSASYSNOTREADY     : Result:= 'Network subsystem is unusable';
  645.     WSAVERNOTSUPPORTED : Result:= 'Winsock DLL cannot support this application';
  646.     WSANOTINITIALISED  : Result:= 'Winsock not initialized';
  647.     WSAHOST_NOT_FOUND  : Result:= 'Host not found';
  648.     WSATRY_AGAIN       : Result:= 'Non authoritative - host not found';
  649.     WSANO_RECOVERY     : Result:= 'Non recoverable error';
  650.     WSANO_DATA         : Result:= 'Valid name, no data record of requested type'
  651.   else
  652.     Result:= 'Not a Winsock error';
  653.   end;
  654. end;
  655. function TCustomWSocket.GetLocalHostAddress: string;
  656. var
  657.   SockAddrIn: TSockAddrIn;
  658.   HostEnt: PHostEnt;
  659.   szHostName: array[0..128] of char;
  660. begin
  661.   if gethostname(szHostName, 128) = 0 then
  662.     begin
  663.       HostEnt:= gethostbyname(szHostName);
  664.       if HostEnt = nil then
  665.         Result:= ''
  666.       else
  667.         begin
  668.           SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^);
  669.           Result:= inet_ntoa(SockAddrIn.sin_addr);
  670.         end;
  671.     end
  672.   else
  673.     SocketError(WSAGetLastError);
  674. end;
  675. function TCustomWSocket.GetLocalHostName: string;
  676. var
  677.   szHostName: array[0..128] of char;
  678. begin
  679.   if gethostname(szHostName, 128) = 0 then
  680.     Result:= szHostName
  681.   else
  682.     SocketError(WSAGetLastError);
  683. end;
  684. (**** TTCPClient Class ****)
  685. constructor TTCPClient.Create(AOwner: TComponent);
  686. begin
  687.   inherited Create(AOwner);
  688.   FHandle:= AllocateHWnd(WndProc);
  689.   FProtocol:= IPPROTO_TCP;
  690.   FType:= SOCK_STREAM;
  691. end;
  692. destructor TTCPClient.Destroy;
  693. begin
  694.   Close;
  695.   DeallocateHWnd(FHandle);
  696.   inherited Destroy;
  697. end;
  698. procedure TTCPClient.OpenConnection(Socket: TSocket; Error: word);
  699. var
  700.   EventMask: longint;
  701. begin
  702.   if Error <> 0 then
  703.     SocketError(Error)
  704.   else
  705.     begin
  706.       EventMask:= FD_READ or FD_CLOSE;
  707.       if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  708.         SocketError(WSAGetLastError)
  709.       else
  710.         begin
  711.           if Assigned(FOnConnect) then
  712.             FOnConnect(Self, Socket);
  713.           FSocketState:= ssConnected;
  714.         end;
  715.     end;
  716. end;
  717. procedure TTCPClient.CloseConnection(Socket: TSocket; Error: word);
  718. begin
  719.   if Error = WSAENETDOWN then
  720.     SocketError(Error)
  721.   else
  722.     begin
  723.       if Assigned(FOnClose) then
  724.         FOnClose(Self, Socket);
  725.       Close;
  726.     end;
  727. end;
  728. procedure TTCPClient.IncommingData(Socket: TSocket; Error: word);
  729. begin
  730.   if Error <> 0 then
  731.     SocketError(Error)
  732.   else
  733.     if Assigned(FOnData) then
  734.       FOnData(Self, Socket);
  735. end;
  736. procedure TTCPClient.WndProc(var AMsg: TMessage);
  737. var
  738.   Error: word;
  739. begin
  740.   with AMsg do
  741.     case Msg of
  742.       WM_ASYNCSELECT:
  743.         begin
  744.           if (FSocketState = ssClosed) then
  745.             Exit;
  746.           Error:= WSAGetSelectError(LParam);
  747.           case WSAGetSelectEvent(LParam) of
  748.             FD_READ   : IncommingData(WParam, Error);
  749.             FD_CONNECT: OpenConnection(WParam, Error);
  750.             FD_CLOSE  : CloseConnection(WParam, Error);
  751.           else
  752.             if Error <> 0 then
  753.               SocketError(Error);
  754.           end;
  755.         end;
  756.     else
  757.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  758.     end;
  759. end;
  760. procedure TTCPClient.Open;
  761. var
  762.   SockAddrIn: TSockAddrIn;
  763.   SockOpt: LongBool;
  764.   EventMask: longint;
  765. begin
  766.   if (FSocketState <> ssClosed) then
  767.     Exit;
  768.   if not GetSockAddrIn(FHost, FPort, SockAddrIn) then
  769.     Exit;
  770.   FLocalSocket:= socket(PF_INET, FType, 0);
  771.   if FLocalSocket = INVALID_SOCKET then
  772.     begin
  773.       SocketError(WSAGetLastError);
  774.       Exit;
  775.     end;
  776.   EventMask:= (FD_CONNECT or FD_READ or FD_CLOSE);
  777.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  778.     begin
  779.       SocketError(WSAGetLastError);
  780.       closesocket(FLocalSocket);
  781.       Exit;
  782.     end;
  783.   SockOpt:= true; {Enable OOB Data inline}
  784.   if setsockopt(FLocalSocket, SOL_SOCKET, SO_OOBINLINE, PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then
  785.     begin
  786.       SocketError(WSAGetLastError);
  787.       closesocket(FLocalSocket);
  788.       Exit;
  789.     end;
  790.   if connect(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  791.     begin
  792.       if WSAGetLastError <> WSAEWOULDBLOCK then
  793.         begin
  794.           SocketError(WSAGetLastError);
  795.           closesocket(FLocalSocket);
  796.           Exit;
  797.         end;
  798.     end;
  799.   FSocketState:= ssOpen;
  800. end;
  801. procedure TTCPClient.Close;
  802. begin
  803.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  804.     Exit;
  805.   SocketClose(FLocalSocket, FHandle);
  806.   if FLocalSocket = INVALID_SOCKET then
  807.     FSocketState:= ssClosed;
  808. end;
  809. procedure TTCPClient.Write(Data: string);
  810. begin
  811.   SocketWrite(FLocalSocket, 0, Data);
  812. end;
  813. function TTCPClient.Read: string;
  814. begin
  815.   Result:= SocketRead(FLocalSocket, 0);
  816. end;
  817. function TTCPClient.Peek: string;
  818. begin
  819.   Result:= SocketRead(FLocalSocket, MSG_PEEK);
  820. end;
  821. function TTCPClient.WriteBuffer(Buffer: Pointer; Size: integer): integer;
  822. begin
  823.   Result:= SocketWriteBuffer(FLocalSocket, Buffer, Size, 0);
  824. end;
  825. function TTCPClient.ReadBuffer(Buffer: Pointer; Size: integer): integer;
  826. begin
  827.   Result:= SocketReadBuffer(FLocalSocket, Buffer, Size, 0);
  828. end;
  829. function TTCPClient.GetPeerAddress: string;
  830. begin
  831.   Result:= PeerToAddress(FLocalSocket);
  832. end;
  833. function TTCPClient.GetPeerPort: string;
  834. begin
  835.   Result:= PeerToPort(FLocalSocket);
  836. end;
  837. (**** TTCPServer Class ****)
  838. constructor TTCPServer.Create(AOwner: TComponent);
  839. begin
  840.   inherited Create(AOwner);
  841.   FHandle:= AllocateHWnd(WndProc);
  842.   FProtocol:= IPPROTO_TCP;
  843.   FType:= SOCK_STREAM;
  844.   FClients:= TClientList.Create;
  845. end;
  846. destructor TTCPServer.Destroy;
  847. begin
  848.   Close;
  849.   DeallocateHWnd(FHandle);
  850.   FClients.Free;
  851.   inherited Destroy;
  852. end;
  853. procedure TTCPServer.OpenConnection(Socket: TSocket; Error: word);
  854. var
  855.   Len: integer;
  856.   NewSocket: TSocket;
  857.   SockAddrIn: TSockAddrIn;
  858.   SockOpt: LongBool;
  859.   EventMask: longint;
  860. begin
  861.   if Error <> 0 then
  862.     SocketError(Error)
  863.   else
  864.     begin
  865.       Len:= SizeOf(SockAddrIn);
  866.       {$IFDEF VER140} // Delphi 6
  867.       NewSocket:= accept(FLocalSocket, @SockAddrIn, @Len);
  868.       {$ELSE}         // Delphi 2
  869.       NewSocket:= accept(FLocalSocket, SockAddrIn, Len);
  870.       {$ENDIF}
  871.       if NewSocket = INVALID_SOCKET then
  872.         begin
  873.           SocketError(WSAGetLastError);
  874.           Exit;
  875.         end;
  876.       EventMask:= (FD_READ or FD_CLOSE);
  877.       if WSAASyncSelect(NewSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  878.         begin
  879.           SocketError(WSAGetLastError);
  880.           closesocket(NewSocket);
  881.           Exit;
  882.         end;
  883.       SockOpt:= true; {Enable OOB Data inline}
  884.       if setsockopt(NewSocket, SOL_SOCKET, SO_OOBINLINE , PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then
  885.         begin
  886.           SocketError(WSAGetLastError);
  887.           closesocket(NewSocket);
  888.           Exit;
  889.         end;
  890.       if not FClients.Add(NewSocket) then
  891.         SocketClose(NewSocket, FHandle)
  892.       else
  893.         if Assigned(FOnAccept) then
  894.           FOnAccept(Self, NewSocket);
  895.     end;
  896. end;
  897. procedure TTCPServer.CloseConnection(Socket: TSocket; Error: word);
  898. begin
  899.   if Error = WSAENETDOWN then
  900.     SocketError(Error)
  901.   else
  902.     begin
  903.       if Assigned(FOnClose) then
  904.         FOnClose(Self, Socket);
  905.       Disconnect(Socket);
  906.     end;
  907. end;
  908. procedure TTCPServer.IncommingData(Socket: TSocket; Error: word);
  909. begin
  910.   if Error <> 0 then
  911.     SocketError(Error)
  912.   else
  913.     if Assigned(FOnData) then
  914.       FOnData(Self, Socket);
  915. end;
  916. procedure TTCPServer.WndProc(var AMsg: TMessage);
  917. var
  918.   Error: word;
  919. begin
  920.   with AMsg do
  921.     case Msg of
  922.       WM_ASYNCSELECT:
  923.         begin
  924.           if (FSocketState = ssClosed) then
  925.             Exit;
  926.           Error:= WSAGetSelectError(LParam);
  927.           case WSAGetSelectEvent(LParam) of
  928.             FD_READ  : IncommingData(WParam, Error);
  929.             FD_ACCEPT: OpenConnection(WParam, Error);
  930.             FD_CLOSE : CloseConnection(WParam, Error);
  931.           else
  932.             if Error <> 0 then
  933.               SocketError(Error);
  934.           end;
  935.         end;
  936.     else
  937.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  938.     end;
  939. end;
  940. procedure TTCPServer.Open;
  941. var
  942.   SockAddrIn: TSockAddrIn;
  943. begin
  944.   if (FSocketState <> ssClosed) then
  945.     Exit;
  946.   if not GetAnySockAddrIn(FPort, SockAddrIn) then
  947.     Exit;
  948.   FLocalSocket:= socket(PF_INET, FType, 0);
  949.   if FLocalSocket = INVALID_SOCKET then
  950.     begin
  951.       SocketError(WSAGetLastError);
  952.       Exit;
  953.     end;
  954.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, FD_ACCEPT) <> 0 then
  955.     begin
  956.       SocketError(WSAGetLastError);
  957.       closesocket(FLocalSocket);
  958.       Exit;
  959.     end;
  960.   if bind(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  961.     begin
  962.       SocketError(WSAGetLastError);
  963.       closesocket(FLocalSocket);
  964.       Exit;
  965.     end;
  966.   if listen(FLocalSocket, 5) <> 0 then
  967.     begin
  968.       SocketError(WSAGetLastError);
  969.       closesocket(FLocalSocket);
  970.       Exit;
  971.     end;
  972.   FSocketState:= ssListening;
  973. end;
  974. procedure TTCPServer.Close;
  975. var
  976.   i: integer;
  977.   Dummy: TSocket;
  978. begin
  979.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  980.     Exit;
  981.   for i:= 0 to FClients.Count-1 do
  982.     begin
  983.       Dummy:= FClients[i];
  984.       SocketClose(Dummy, FHandle);
  985.     end;
  986.   FClients.Clear;
  987.   SocketClose(FLocalSocket, FHandle);
  988.   if FLocalSocket = INVALID_SOCKET then
  989.     FSocketState:= ssClosed;
  990. end;
  991. procedure TTCPServer.Write(Socket: TSocket; Data: string);
  992. begin
  993.   SocketWrite(Socket, 0, Data);
  994. end;
  995. function TTCPServer.Read(Socket: TSocket): string;
  996. begin
  997.   Result:= SocketRead(Socket, 0);
  998. end;
  999. function TTCPServer.Peek(Socket: TSocket): string;
  1000. begin
  1001.   Result:= SocketRead(Socket, MSG_PEEK);
  1002. end;
  1003. function TTCPServer.WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  1004. begin
  1005.   Result:= SocketWriteBuffer(Socket, Buffer, Size, 0);
  1006. end;
  1007. function TTCPServer.ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  1008. begin
  1009.   Result:= SocketReadBuffer(Socket, Buffer, Size, 0);
  1010. end;
  1011. procedure TTCPServer.Disconnect(Socket: TSocket);
  1012. begin
  1013.   FClients.Delete(Socket);
  1014.   SocketClose(Socket, FHandle);
  1015. end;
  1016. end.