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

Delphi控件源码

开发平台:

Delphi

  1. unit WSockets;
  2. {
  3. WSockets Version 1.20 - A Simple VCL Encapsulation of the WinSocket API
  4. VCL Classes in this Unit:
  5.   TTCPClient - A TCP Client (derived from TCustomWSocket)
  6.   TTCPServer - A TCP Server (derived from TCustomWSocket)
  7.   TUDPClient - A UDP Client (derived from TCustomWSocket)
  8.   TUDPServer - A UDP Server (derived from TCustomWSocket)
  9. Other classes ni this Unit:
  10.   TCustomWSocket - A generic base class for other socket classes
  11.   TClientList    - A list class used only by the TTCPServer class
  12. Legal issues:
  13. Copyright (C) 1997 by Robert T. Palmqvist <robert.palmqvist@skanska.se>
  14.   This software is provided 'as-is', without any express or implied
  15.   warranty.  In no event will the author be held liable for any damages
  16.   arising from the use of this software.
  17.   Permission is granted to anyone to use this software for any purpose,
  18.   including commercial applications, and to alter it and redistribute it
  19.   freely, subject to the following restrictions:
  20.   1. The origin of this software must not be misrepresented, you must not
  21.      claim that you wrote the original software. If you use this software
  22.      in a product, an acknowledgment in the product documentation would be
  23.      appreciated but is not required.
  24.   2. Altered source versions must be plainly marked as such, and must not be
  25.      misrepresented as being the original software.
  26.   3. This notice may not be removed or altered from any source distribution.
  27. Credits go to:
  28.   Gary T. Desrosiers. His unit "Sockets" inspired me to write my own.
  29.   Martin Hall, Mark Towfig, Geoff Arnold, David Treadwell, Henry Sanders
  30.   and InfoMagic, Inc. for their Windows Help File "WinSock.hlp".
  31.   All the guys at Borland who gave us a marvellous tool named "Delphi"!
  32. Recommended information sources:
  33.   Specification:
  34.     Windows Sockets Version 1.1 Specification
  35.   Textbook:
  36.     Quinn and Shute. "Windows Sockets Network Programming"
  37.     1996 by Addison-Wesley Publishing Company, Inc. ISBN 0-201-63372-8
  38.   World Wide Web:
  39.     http://www.sockets.com
  40.     http://www.stardust.com
  41.   Network News:
  42.     alt.winsock.programming
  43.   Frequently Asked Questions:
  44.     "WinSock Application FAQ" Mailto: info@lcs.com Subject: faq
  45.   Requests for Comments:
  46.     RFC 768 "User Datagram Protocol"
  47.     RFC 791 "Internet Protocol"
  48.     RFC 793 "Transmission Control Protocol"
  49. }
  50. interface
  51. uses
  52.   Windows, WinSock, sysutils, Classes, Messages;
  53. const
  54.   WM_ASYNCSELECT = WM_USER + 1;
  55.   READ_BUFFER_SIZE = 1024;
  56.   MAX_LOOP = 100;
  57. type
  58.   TSocketState = (ssNotStarted, ssClosed, ssConnected, ssListening, ssOpen);
  59.   TOnError = procedure(Sender: TObject; Error: integer; Msg: string) of object;
  60.   TOnData = procedure(Sender: TObject; Socket: TSocket) of object;
  61.   TOnAccept = procedure(Sender: TObject; Socket: TSocket) of object;
  62.   TOnConnect = procedure(Sender: TObject; Socket: TSocket) of object;
  63.   TOnClose = procedure(Sender: TObject; Socket: TSocket) of object;
  64.   TReadBuffer = array[1..READ_BUFFER_SIZE] of byte;
  65.   TClientList = class(TObject)
  66.   private
  67.     FSockets: TList;
  68.   protected
  69.     function GetSockets(Index: integer): TSocket;
  70.     function GetCount: integer;
  71.   public
  72.     constructor Create;
  73.     destructor Destroy; override;
  74.     function Add(Socket: TSocket): boolean;
  75.     procedure Delete(Socket: TSocket);
  76.     procedure Clear;
  77.     function IndexOf(Socket: TSocket): integer;
  78.     property Sockets[Index: integer]: TSocket read GetSockets; default;
  79.     property Count: integer read GetCount;
  80.   end;
  81.   TCustomWSocket = class(TComponent)
  82.   private
  83.     {WinSocket Information Private Fields}
  84.     FVersion: string;
  85.     FDescription: string;
  86.     FSystemStatus: string;
  87.     FMaxSockets: integer;
  88.     FMaxUDPSize: integer;
  89.     {End WinSocket Information Private Fields}
  90.     FProtocol: integer;
  91.     FType: integer;
  92.     FReadBuffer: TReadBuffer;
  93.     FLocalSocket: TSocket;
  94.     FSocketState: TSocketState;
  95.     FLastError: integer;
  96.     FOnError: TOnError;
  97.   protected
  98.     procedure SocketError(Error: integer);
  99.     function LastErrorDesc: string;
  100.     function GetLocalHostAddress: string;
  101.     function GetLocalHostName: string;
  102.     {Socket Helper Functions}
  103.     procedure SocketClose(var Socket: TSocket; Handle: HWND);
  104.     function SocketQueueSize(Socket: TSocket): longint;
  105.     procedure SocketWrite(Socket: TSocket; Flag: integer; Data: string);
  106.     function SocketRead(Socket: TSocket; Flag: integer): string;
  107.     function SocketWriteBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  108.     function SocketReadBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  109.     procedure SocketWriteTo(Socket: TSocket; Flag: integer; Data: string; var SockAddrIn: TSockAddrIn);
  110.     function SocketReadFrom(Socket: TSocket; Flag: integer; var SockAddrIn: TSockAddrIn): string;
  111.     function SocketWriteBufferTo(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  112.     function SocketReadBufferFrom(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  113.   public
  114.     constructor Create(AOwner: TComponent); override;
  115.     destructor Destroy; override;
  116.     {Address and Port Resolving Helper Functions}
  117.     function GetSockAddrIn(Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
  118.     function GetAnySockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
  119.     function GetBroadcastSockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
  120.     function SockAddrInToName(SockAddrIn: TSockAddrIn): string;
  121.     function SockAddrInToAddress(SockAddrIn: TSockAddrIn): string;
  122.     function SockAddrInToPort(SockAddrIn: TSockAddrIn): string;
  123.     function SocketToName(Socket: TSocket): string;
  124.     function SocketToAddress(Socket: TSocket): string;
  125.     function SocketToPort(Socket: TSocket): string;
  126.     function PeerToName(Socket: TSocket): string;
  127.     function PeerToAddress(Socket: TSocket): string;
  128.     function PeerToPort(Socket: TSocket): string;
  129.     {WinSocket Information Properties}
  130.     property Version: string read FVersion;
  131.     property Description: string read FDescription;
  132.     property SystemStatus: string read FSystemStatus;
  133.     property MaxSockets: integer read FMaxSockets;
  134.     property MaxUDPSize: integer read FMaxUDPSize;
  135.     {End WinSocket Information Properties}
  136.     property LocalSocket: TSocket read FLocalSocket;
  137.     property SocketState: TSocketState read FSocketState;
  138.     property LastError: integer read FLastError;
  139.     property LocalHostAddress: string read GetLocalHostAddress;
  140.     property LocalHostName: string read GetLocalHostName;
  141.   published
  142.     property OnError: TOnError read FOnError write FOnError;
  143.   end;
  144.   TTCPClient = class(TCustomWSocket)
  145.   private
  146.     FHandle: HWND;
  147.     FHost: string;
  148.     FPort: string;
  149.     FOnData: TOnData;
  150.     FOnConnect: TOnConnect;
  151.     FOnClose: TOnClose;
  152.   protected
  153.     procedure WndProc(var AMsg: TMessage);
  154.     procedure OpenConnection(Socket: TSocket; Error: word);
  155.     procedure IncommingData(Socket: TSocket; Error: word);
  156.     procedure CloseConnection(Socket: TSocket; Error: word);
  157.     function GetPeerAddress: string;
  158.     function GetPeerPort: string;
  159.   public
  160.     constructor Create(AOwner: TComponent); override;
  161.     destructor Destroy; override;
  162.     procedure Open;
  163.     procedure Close;
  164.     function Peek: string;
  165.     procedure Write(Data: string);
  166.     function Read: string;
  167.     function WriteBuffer(Buffer: Pointer; Size: integer): integer;
  168.     function ReadBuffer(Buffer: Pointer; Size: integer): integer;
  169.     property Handle: HWND read FHandle;
  170.     property PeerAddress: string read GetPeerAddress;
  171.     property PeerPort: string read GetPeerPort;
  172.   published
  173.     property Host: string read FHost write FHost;
  174.     property Port: string read FPort write FPort;
  175.     property OnData: TOnData read FOnData write FOnData;
  176.     property OnConnect: TOnConnect read FOnConnect write FOnConnect;
  177.     property OnClose: TOnClose read FOnClose write FOnClose;
  178.   end;
  179.   TTCPServer = class(TCustomWSocket)
  180.   private
  181.     FHandle: HWND;
  182.     FPort: string;
  183.     FOnData: TOnData;
  184.     FOnAccept: TOnAccept;
  185.     FOnClose: TOnClose;
  186.     FClients: TClientList;
  187.   protected
  188.     procedure WndProc(var AMsg: TMessage);
  189.     procedure OpenConnection(Socket: TSocket; Error: word);
  190.     procedure IncommingData(Socket: TSocket; Error: word);
  191.     procedure CloseConnection(Socket: TSocket; Error: word);
  192.   public
  193.     constructor Create(AOwner: TComponent); override;
  194.     destructor Destroy; override;
  195.     procedure Open;
  196.     procedure Close;
  197.     function Peek(Socket: TSocket): string;
  198.     procedure Write(Socket: TSocket; Data: string);
  199.     function Read(Socket: TSocket): string;
  200.     function WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  201.     function ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  202.     procedure Disconnect(Socket: TSocket);
  203.     property Handle: HWND read FHandle;
  204.     property Clients: TClientList read FClients;
  205.   published
  206.     property Port: string read FPort write FPort;
  207.     property OnData: TOnData read FOnData write FOnData;
  208.     property OnAccept: TOnAccept read FOnAccept write FOnAccept;
  209.     property OnClose: TOnClose read FOnClose write FOnClose;
  210.   end;
  211.   TUDPClient = class(TCustomWSocket)
  212.   private
  213.     FHandle: HWND;
  214.     FHost: string;
  215.     FPort: string;
  216.     FOnData: TOnData;
  217.   protected
  218.     procedure WndProc(var AMsg: TMessage);
  219.     procedure IncommingData(Socket: TSocket; Error: word);
  220.     function GetPeerAddress: string;
  221.     function GetPeerPort: string;
  222.   public
  223.     constructor Create(AOwner: TComponent); override;
  224.     destructor Destroy; override;
  225.     procedure Open;
  226.     procedure Close;
  227.     function Peek: string;
  228.     procedure Write(Data: string);
  229.     function Read: string;
  230.     function WriteBuffer(Buffer: Pointer; Size: integer): integer;
  231.     function ReadBuffer(Buffer: Pointer; Size: integer): integer;
  232.     property Handle: HWND read FHandle;
  233.     property PeerAddress: string read GetPeerAddress;
  234.     property PeerPort: string read GetPeerPort;
  235.   published
  236.     property Host: string read FHost write FHost;
  237.     property Port: string read FPort write FPort;
  238.     property OnData: TOnData read FOnData write FOnData;
  239.   end;
  240.   TUDPServer = class(TCustomWSocket)
  241.   private
  242.     FHandle: HWND;
  243.     FPort: string;
  244.     FOnData: TOnData;
  245.   protected
  246.     procedure WndProc(var AMsg: TMessage);
  247.     procedure IncommingData(Socket: TSocket; Error: word);
  248.   public
  249.     constructor Create(AOwner: TComponent); override;
  250.     destructor Destroy; override;
  251.     procedure Open;
  252.     procedure Close;
  253.     function Peek(Socket: TSocket; var SockAddrIn: TSockAddrIn): string;
  254.     procedure Write(Socket: TSocket; Data: string; var SockAddrIn: TSockAddrIn);
  255.     function Read(Socket: TSocket; var SockAddrIn: TSockAddrIn): string;
  256.     function WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer; var SockAddrIn: TSockAddrIn): integer;
  257.     function ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer; var SockAddrIn: TSockAddrIn): integer;
  258.     property Handle: HWND read FHandle;
  259.   published
  260.     property Port: string read FPort write FPort;
  261.     property OnData: TOnData read FOnData write FOnData;
  262.   end;
  263. procedure Register;
  264. implementation
  265. procedure Register;
  266. begin
  267.   RegisterComponents('Samples', [TTCPClient, TTCPServer, TUDPClient, TUDPServer]);
  268. end;
  269. (**** TClientList Class ****)
  270. constructor TClientList.Create;
  271. begin
  272.   inherited Create;
  273.   FSockets:= TList.Create;
  274. end;
  275. destructor TClientList.Destroy;
  276. begin
  277.   Clear;
  278.   FSockets.Free;
  279.   inherited Destroy;
  280. end;
  281. function TClientList.GetSockets(Index: integer): TSocket;
  282. begin
  283.   Result:= TSocket(FSockets[Index]);
  284. end;
  285. function TClientList.GetCount: integer;
  286. begin
  287.   Result:= FSockets.Count;
  288. end;
  289. function TClientList.Add(Socket: TSocket): boolean;
  290. begin
  291.   Result:= (FSockets.Add(Ptr(Socket)) >= 0);
  292. end;
  293. procedure TClientList.Delete(Socket: TSocket);
  294. var
  295.   i: integer;
  296. begin
  297.   for i:= 0 to FSockets.Count-1 do
  298.     begin
  299.       if TSocket(FSockets[i]) = Socket then
  300.         begin
  301.           FSockets.Delete(i);
  302.           Break;
  303.         end;
  304.     end;
  305. end;
  306. procedure TClientList.Clear;
  307. begin
  308.   FSockets.Clear;
  309. end;
  310. function TClientList.IndexOf(Socket: TSocket): integer;
  311. var
  312.   i: integer;
  313. begin
  314.   Result:= -1;
  315.   for i:= 0 to FSockets.Count-1 do
  316.     begin
  317.       if TSocket(FSockets[i]) = Socket then
  318.         begin
  319.           Result:= i;
  320.           Break;
  321.         end;
  322.     end;
  323. end;
  324. (**** TCustomWSocket Class ****)
  325. constructor TCustomWSocket.Create(AOwner: TComponent);
  326. var
  327.   WSAData: TWSAData;
  328. begin
  329.   inherited Create(AOwner);
  330.   FProtocol:= IPPROTO_IP;
  331.   FType:= SOCK_RAW;
  332.   FLocalSocket:= INVALID_SOCKET;
  333.   FSocketState:= ssNotStarted;
  334.   FLastError:= WSAStartup($101, WSAData);
  335.   if FLastError = 0 then
  336.     begin
  337.       FSocketState:= ssClosed;
  338.       with WSAData do
  339.         begin
  340.           FVersion:= Concat(IntToStr(Hi(wVersion)),'.',(IntToStr(Lo(wVersion))));
  341.           FDescription:= StrPas(szDescription);
  342.          FSystemStatus:= StrPas(szSystemStatus);
  343.           FMaxSockets:= iMaxSockets;
  344.           FMaxUDPSize:= iMaxUDPDg;
  345.         end;
  346.     end
  347.   else
  348.     SocketError(FLastError);
  349. end;
  350. destructor TCustomWSocket.Destroy;
  351. begin
  352.   if FLocalSocket <> INVALID_SOCKET then
  353.     closesocket(FLocalSocket);
  354.   if FSocketState <> ssNotStarted then
  355.     if WSACleanUp = SOCKET_ERROR then
  356.       SocketError(WSAGetLastError);
  357.   inherited Destroy;
  358. end;
  359. function TCustomWSocket.GetSockAddrIn(
  360.          Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
  361. var
  362.   ProtoEnt: PProtoEnt;
  363.   ServEnt: PServEnt;
  364.   HostEnt: PHostEnt;
  365. begin
  366.   Result:= false;
  367.   SockAddrIn.sin_family:= AF_INET;
  368.   ProtoEnt:= getprotobynumber(FProtocol);
  369.   if ProtoEnt = nil then
  370.     begin
  371.       SocketError(WSAGetLastError);
  372.       Exit;
  373.     end;
  374.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  375.   if ServEnt = nil then
  376.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  377.   else
  378.     SockAddrIn.sin_port:= ServEnt^.s_port;
  379.   SockAddrIn.sin_addr.s_addr:= inet_addr(PChar(Host));
  380.   if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
  381.     begin
  382.       HostEnt:= gethostbyname(PChar(Host));
  383.       if HostEnt = nil then
  384.         begin
  385.          SocketError(WSAGetLastError);
  386.          Exit;
  387.         end;
  388.       SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^);
  389.     end;
  390.   Result:= true;
  391. end;
  392. function TCustomWSocket.GetAnySockAddrIn(
  393.          Port: string; var SockAddrIn: TSockAddrIn): boolean;
  394. var
  395.   ProtoEnt: PProtoEnt;
  396.   ServEnt: PServEnt;
  397. begin
  398.   Result:= false;
  399.   SockAddrIn.sin_family:= AF_INET;
  400.   ProtoEnt:= getprotobynumber(FProtocol);
  401.   if ProtoEnt = nil then
  402.     Exit;
  403.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  404.   if ServEnt = nil then
  405.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  406.   else
  407.     SockAddrIn.sin_port:= ServEnt^.s_port;
  408.   SockAddrIn.sin_addr.s_addr:= INADDR_ANY;
  409.   Result:= true;
  410. end;
  411. function TCustomWSocket.GetBroadcastSockAddrIn(
  412.          Port: string; var SockAddrIn: TSockAddrIn): boolean;
  413. var
  414.   ProtoEnt: PProtoEnt;
  415.   ServEnt: PServEnt;
  416. begin
  417.   Result:= false;
  418.   SockAddrIn.sin_family:= AF_INET;
  419.   ProtoEnt:= getprotobynumber(FProtocol);
  420.   if ProtoEnt = nil then
  421.     Exit;
  422.   ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
  423.   if ServEnt = nil then
  424.     SockAddrIn.sin_port:= htons(StrToInt(Port))
  425.   else
  426.     SockAddrIn.sin_port:= ServEnt^.s_port;
  427.   SockAddrIn.sin_addr.s_addr:= INADDR_BROADCAST;
  428.   Result:= true;
  429. end;
  430. function TCustomWSocket.SockAddrInToName(SockAddrIn: TSockAddrIn): string;
  431. var
  432.   HostEnt: PHostEnt;
  433. begin
  434.   HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  435.   if HostEnt <> nil then
  436.     Result:= HostEnt.h_name;
  437. end;
  438. function TCustomWSocket.SockAddrInToAddress(SockAddrIn: TSockAddrIn): string;
  439. begin
  440.   Result:= inet_ntoa(SockAddrIn.sin_addr);
  441. end;
  442. function TCustomWSocket.SockAddrInToPort(SockAddrIn: TSockAddrIn): string;
  443. begin
  444.   Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  445. end;
  446. function TCustomWSocket.SocketToName(Socket: TSocket): string;
  447. var
  448.   SockAddrIn: TSockAddrIn;
  449.   Len: integer;
  450.   HostEnt: PHostEnt;
  451. begin
  452.   if Socket <> INVALID_SOCKET then
  453.     begin
  454.       Len:= SizeOf(SockAddrIn);
  455.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  456.         begin
  457.           HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  458.           if HostEnt <> nil then
  459.             Result:= HostEnt.h_name;
  460.         end;
  461.     end;
  462. end;
  463. function TCustomWSocket.SocketToAddress(Socket: TSocket): string;
  464. var
  465.   SockAddrIn: TSockAddrIn;
  466.   Len: integer;
  467. begin
  468.   if Socket <> INVALID_SOCKET then
  469.     begin
  470.       Len:= SizeOf(SockAddrIn);
  471.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  472.         Result:= inet_ntoa(SockAddrIn.sin_addr);
  473.     end;
  474. end;
  475. function TCustomWSocket.SocketToPort(Socket: TSocket): string;
  476. var
  477.   SockAddrIn: TSockAddrIn;
  478.   Len: integer;
  479. begin
  480.   if Socket <> INVALID_SOCKET then
  481.     begin
  482.       Len:= SizeOf(SockAddrIn);
  483.       if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  484.         Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  485.     end;
  486. end;
  487. function TCustomWSocket.PeerToName(Socket: TSocket): string;
  488. var
  489.   SockAddrIn: TSockAddrIn;
  490.   Len: integer;
  491.   HostEnt: PHostEnt;
  492. begin
  493.   if Socket <> INVALID_SOCKET then
  494.     begin
  495.       Len:= SizeOf(SockAddrIn);
  496.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  497.         begin
  498.           HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
  499.           if HostEnt <> nil then
  500.             Result:= HostEnt.h_name;
  501.         end;
  502.     end;
  503. end;
  504. function TCustomWSocket.PeerToAddress(Socket: TSocket): string;
  505. var
  506.   SockAddrIn: TSockAddrIn;
  507.   Len: integer;
  508. begin
  509.   if Socket <> INVALID_SOCKET then
  510.     begin
  511.       Len:= SizeOf(SockAddrIn);
  512.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  513.         Result:= inet_ntoa(SockAddrIn.sin_addr);
  514.     end;
  515. end;
  516. function TCustomWSocket.PeerToPort(Socket: TSocket): string;
  517. var
  518.   SockAddrIn: TSockAddrIn;
  519.   Len: integer;
  520. begin
  521.   if Socket <> INVALID_SOCKET then
  522.     begin
  523.       Len:= SizeOf(SockAddrIn);
  524.       if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then
  525.         Result:= IntToStr(ntohs(SockAddrIn.sin_port));
  526.     end;
  527. end;
  528. procedure TCustomWSocket.SocketClose(var Socket: TSocket; Handle: HWND);
  529. var
  530.   RC: integer;
  531. begin
  532.   if Socket <> INVALID_SOCKET then
  533.     begin
  534.       if WSAASyncSelect(Socket, Handle, WM_ASYNCSELECT, 0) <> 0 then
  535.         begin
  536.           SocketError(WSAGetLastError);
  537.           Exit;
  538.         end;
  539.       if shutdown(Socket, 1) <> 0 then
  540.         if WSAGetLastError <> WSAENOTCONN then
  541.           begin
  542.             SocketError(WSAGetLastError);
  543.             Exit;
  544.           end;
  545.       repeat
  546.         RC:= recv(Socket, FReadBuffer, SizeOf(TReadBuffer), 0);
  547.       until (RC = 0) or (RC = SOCKET_ERROR);
  548.       if closesocket(Socket) <> 0 then
  549.         SocketError(WSAGetLastError)
  550.       else
  551.         Socket:= INVALID_SOCKET;
  552.     end;
  553. end;
  554. function TCustomWSocket.SocketQueueSize(Socket: TSocket): longint;
  555. var
  556.   Size: longint;
  557. begin
  558.   Result:= 0;
  559.   if ioctlsocket(Socket, FIONREAD, Size) <> 0 then
  560.     SocketError(WSAGetLastError)
  561.   else
  562.     Result:= Size;
  563. end;
  564. procedure TCustomWSocket.SocketWrite(Socket: TSocket; Flag: integer; Data: string);
  565. var
  566.   TotSent, ToSend, Sent, ErrorLoop: integer;
  567. begin
  568.   if Data <> '' then
  569.     begin
  570.       ErrorLoop:= 0;
  571.       TotSent:= 0;
  572.       ToSend:= Length(Data);
  573.       repeat
  574.         Sent:= send(Socket, Data[TotSent+1], (ToSend-TotSent), Flag);
  575.         if Sent = SOCKET_ERROR then
  576.           begin
  577.             Inc(ErrorLoop);
  578.             if WSAGetLastError <> WSAEWOULDBLOCK then
  579.               begin
  580.                 SocketError(WSAGetLastError);
  581.                 Exit;
  582.               end;
  583.           end
  584.         else
  585.           Inc(TotSent, Sent);
  586.       until (TotSent >= ToSend) or (ErrorLoop > MAX_LOOP);
  587.     end;
  588. end;
  589. function TCustomWSocket.SocketRead(Socket: TSocket; Flag: integer): string;
  590. var
  591.   Received: longint;
  592. begin
  593.   Result:= '';
  594.   Received:= recv(Socket, FReadBuffer, SizeOf(TReadBuffer), Flag);
  595.   if Received = SOCKET_ERROR then
  596.     begin
  597.       if WSAGetLastError <> WSAEWOULDBLOCK then
  598.         SocketError(WSAGetLastError);
  599.     end
  600.   else
  601.     begin
  602.       SetLength(Result, Received);
  603.       Move(FReadBuffer, Result[1], Received);
  604.     end;
  605. end;
  606. function TCustomWSocket.SocketWriteBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  607. begin
  608.   Result:= send(Socket, Buffer^, Size, Flag);
  609.   if Result = SOCKET_ERROR then
  610.     begin
  611.       Result:= 0;
  612.       if WSAGetLastError <> WSAEWOULDBLOCK then
  613.         SocketError(WSAGetLastError);
  614.     end;
  615. end;
  616. function TCustomWSocket.SocketReadBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
  617. begin
  618.   Result:= recv(Socket, Buffer^, Size, Flag);
  619.   if Result = SOCKET_ERROR then
  620.     begin
  621.       Result:= 0;
  622.       if WSAGetLastError <> WSAEWOULDBLOCK then
  623.         SocketError(WSAGetLastError);
  624.     end;
  625. end;
  626. procedure TCustomWSocket.SocketWriteTo(Socket: TSocket; Flag: integer; Data: string; var SockAddrIn: TSockAddrIn);
  627. var
  628.   TotSent, ToSend, Sent, ErrorLoop: integer;
  629. begin
  630.   if Data <> '' then
  631.     begin
  632.       ErrorLoop:= 0;
  633.       TotSent:= 0;
  634.       ToSend:= Length(Data);
  635.       repeat
  636.         Sent:= sendto(Socket, Data[TotSent+1], (ToSend-TotSent), Flag, SockAddrIn, SizeOf(SockAddrIn));
  637.         if Sent = SOCKET_ERROR then
  638.           begin
  639.             Inc(ErrorLoop);
  640.             if WSAGetLastError <> WSAEWOULDBLOCK then
  641.               begin
  642.                 SocketError(WSAGetLastError);
  643.                 Exit;
  644.               end;
  645.           end
  646.         else
  647.           Inc(TotSent, Sent);
  648.       until (TotSent >= ToSend) or (ErrorLoop > MAX_LOOP);
  649.     end;
  650. end;
  651. function TCustomWSocket.SocketReadFrom(Socket: TSocket; Flag: integer; var SockAddrIn: TSockAddrIn): string;
  652. var
  653.   Len: integer;
  654.   Received: longint;
  655. begin
  656.   Len:= SizeOf(SockAddrIn);
  657.   Received:= recvfrom(Socket, FReadBuffer, SizeOf(TReadBuffer), Flag, SockAddrIn, Len);
  658.   if Received = SOCKET_ERROR then
  659.     begin
  660.       if WSAGetLastError <> WSAEWOULDBLOCK then
  661.         SocketError(WSAGetLastError);
  662.     end
  663.   else
  664.     begin
  665.       SetLength(Result, Received);
  666.       Move(FReadBuffer, Result[1], Received);
  667.     end;
  668. end;
  669. function TCustomWSocket.SocketWriteBufferTo(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  670. begin
  671.   Result:= sendto(Socket, Buffer^, Size, Flag, SockAddrIn, SizeOf(SockAddrIn));
  672.   if Result = SOCKET_ERROR then
  673.     begin
  674.       Result:= 0;
  675.       if WSAGetLastError <> WSAEWOULDBLOCK then
  676.         SocketError(WSAGetLastError);
  677.     end;
  678. end;
  679. function TCustomWSocket.SocketReadBufferFrom(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
  680. var
  681.   Len: integer;
  682. begin
  683.   Len:= SizeOf(SockAddrIn);
  684.   Result:= recvfrom(Socket, Buffer^, Size, Flag, SockAddrIn, Len);
  685.   if Result = SOCKET_ERROR then
  686.     begin
  687.       Result:= 0;
  688.       if WSAGetLastError <> WSAEWOULDBLOCK then
  689.         SocketError(WSAGetLastError);
  690.     end;
  691. end;
  692. procedure TCustomWSocket.SocketError(Error: integer);
  693. begin
  694.   FLastError:= Error;
  695.   if Assigned(FOnError) then
  696.     FOnError(Self, FLastError, LastErrorDesc);
  697. end;
  698. function TCustomWSocket.LastErrorDesc: string;
  699. begin
  700.   case FLastError of
  701.     WSAEINTR           : Result:= 'Interrupted system call';
  702.     WSAEBADF           : Result:= 'Bad file number';
  703.     WSAEACCES          : Result:= 'Permission denied';
  704.     WSAEFAULT          : Result:= 'Bad address';
  705.     WSAEINVAL          : Result:= 'Invalid argument';
  706.     WSAEMFILE          : Result:= 'Too many open files';
  707.     WSAEWOULDBLOCK     : Result:= 'Operation would block';
  708.     WSAEINPROGRESS     : Result:= 'Operation now in progress';
  709.     WSAEALREADY        : Result:= 'Operation already in progress';
  710.     WSAENOTSOCK        : Result:= 'Socket operation on nonsocket';
  711.     WSAEDESTADDRREQ    : Result:= 'Destination address required';
  712.     WSAEMSGSIZE        : Result:= 'Message too long';
  713.     WSAEPROTOTYPE      : Result:= 'Protocol wrong type for socket';
  714.     WSAENOPROTOOPT     : Result:= 'Protocol not available';
  715.     WSAEPROTONOSUPPORT : Result:= 'Protocol not supported';
  716.     WSAESOCKTNOSUPPORT : Result:= 'Socket not supported';
  717.     WSAEOPNOTSUPP      : Result:= 'Operation not supported on socket';
  718.     WSAEPFNOSUPPORT    : Result:= 'Protocol family not supported';
  719.     WSAEAFNOSUPPORT    : Result:= 'Address family not supported';
  720.     WSAEADDRINUSE      : Result:= 'Address already in use';
  721.     WSAEADDRNOTAVAIL   : Result:= 'Can''t assign requested address';
  722.     WSAENETDOWN        : Result:= 'Network is down';
  723.     WSAENETUNREACH     : Result:= 'Network is unreachable';
  724.     WSAENETRESET       : Result:= 'Network dropped connection on reset';
  725.     WSAECONNABORTED    : Result:= 'Software caused connection abort';
  726.     WSAECONNRESET      : Result:= 'Connection reset by peer';
  727.     WSAENOBUFS         : Result:= 'No buffer space available';
  728.     WSAEISCONN         : Result:= 'Socket is already connected';
  729.     WSAENOTCONN        : Result:= 'Socket is not connected';
  730.     WSAESHUTDOWN       : Result:= 'Can''t send after socket shutdown';
  731.     WSAETOOMANYREFS    : Result:= 'Too many references:can''t splice';
  732.     WSAETIMEDOUT       : Result:= 'Connection timed out';
  733.     WSAECONNREFUSED    : Result:= 'Connection refused';
  734.     WSAELOOP           : Result:= 'Too many levels of symbolic links';
  735.     WSAENAMETOOLONG    : Result:= 'File name is too long';
  736.     WSAEHOSTDOWN       : Result:= 'Host is down';
  737.     WSAEHOSTUNREACH    : Result:= 'No route to host';
  738.     WSAENOTEMPTY       : Result:= 'Directory is not empty';
  739.     WSAEPROCLIM        : Result:= 'Too many processes';
  740.     WSAEUSERS          : Result:= 'Too many users';
  741.     WSAEDQUOT          : Result:= 'Disk quota exceeded';
  742.     WSAESTALE          : Result:= 'Stale NFS file handle';
  743.     WSAEREMOTE         : Result:= 'Too many levels of remote in path';
  744.     WSASYSNOTREADY     : Result:= 'Network subsystem is unusable';
  745.     WSAVERNOTSUPPORTED : Result:= 'Winsock DLL cannot support this application';
  746.     WSANOTINITIALISED  : Result:= 'Winsock not initialized';
  747.     WSAHOST_NOT_FOUND  : Result:= 'Host not found';
  748.     WSATRY_AGAIN       : Result:= 'Non authoritative - host not found';
  749.     WSANO_RECOVERY     : Result:= 'Non recoverable error';
  750.     WSANO_DATA         : Result:= 'Valid name, no data record of requested type'
  751.   else
  752.     Result:= 'Not a Winsock error';
  753.   end;
  754. end;
  755. function TCustomWSocket.GetLocalHostAddress: string;
  756. var
  757.   SockAddrIn: TSockAddrIn;
  758.   HostEnt: PHostEnt;
  759.   szHostName: array[0..128] of char;
  760. begin
  761.   if gethostname(szHostName, 128) = 0 then
  762.     begin
  763.       HostEnt:= gethostbyname(szHostName);
  764.       if HostEnt = nil then
  765.         Result:= ''
  766.       else
  767.         begin
  768.           SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^);
  769.           Result:= inet_ntoa(SockAddrIn.sin_addr);
  770.         end;
  771.     end
  772.   else
  773.     SocketError(WSAGetLastError);
  774. end;
  775. function TCustomWSocket.GetLocalHostName: string;
  776. var
  777.   szHostName: array[0..128] of char;
  778. begin
  779.   if gethostname(szHostName, 128) = 0 then
  780.     Result:= szHostName
  781.   else
  782.     SocketError(WSAGetLastError);
  783. end;
  784. (**** TTCPClient Class ****)
  785. constructor TTCPClient.Create(AOwner: TComponent);
  786. begin
  787.   inherited Create(AOwner);
  788.   FHandle:= AllocateHWnd(WndProc);
  789.   FProtocol:= IPPROTO_TCP;
  790.   FType:= SOCK_STREAM;
  791. end;
  792. destructor TTCPClient.Destroy;
  793. begin
  794.   Close;
  795.   DeallocateHWnd(FHandle);
  796.   inherited Destroy;
  797. end;
  798. procedure TTCPClient.OpenConnection(Socket: TSocket; Error: word);
  799. var
  800.   EventMask: longint;
  801. begin
  802.   if Error <> 0 then
  803.     SocketError(Error)
  804.   else
  805.     begin
  806.       EventMask:= FD_READ or FD_CLOSE;
  807.       if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  808.         SocketError(WSAGetLastError)
  809.       else
  810.         begin
  811.           if Assigned(FOnConnect) then
  812.             FOnConnect(Self, Socket);
  813.           FSocketState:= ssConnected;
  814.         end;
  815.     end;
  816. end;
  817. procedure TTCPClient.CloseConnection(Socket: TSocket; Error: word);
  818. begin
  819.   if Error = WSAENETDOWN then
  820.     SocketError(Error)
  821.   else
  822.     begin
  823.       if Assigned(FOnClose) then
  824.         FOnClose(Self, Socket);
  825.       Close;
  826.     end;
  827. end;
  828. procedure TTCPClient.IncommingData(Socket: TSocket; Error: word);
  829. begin
  830.   if Error <> 0 then
  831.     SocketError(Error)
  832.   else
  833.     if Assigned(FOnData) then
  834.       FOnData(Self, Socket);
  835. end;
  836. procedure TTCPClient.WndProc(var AMsg: TMessage);
  837. var
  838.   Error: word;
  839. begin
  840.   with AMsg do
  841.     case Msg of
  842.       WM_ASYNCSELECT:
  843.         begin
  844.           if (FSocketState = ssClosed) then
  845.             Exit;
  846.           Error:= WSAGetSelectError(LParam);
  847.           case WSAGetSelectEvent(LParam) of
  848.             FD_READ   : IncommingData(WParam, Error);
  849.             FD_CONNECT: OpenConnection(WParam, Error);
  850.             FD_CLOSE  : CloseConnection(WParam, Error);
  851.           else
  852.             if Error <> 0 then
  853.               SocketError(Error);
  854.           end;
  855.         end;
  856.     else
  857.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  858.     end;
  859. end;
  860. procedure TTCPClient.Open;
  861. var
  862.   SockAddrIn: TSockAddrIn;
  863.   SockOpt: LongBool;
  864.   EventMask: longint;
  865. begin
  866.   if (FSocketState <> ssClosed) then
  867.     Exit;
  868.   if not GetSockAddrIn(FHost, FPort, SockAddrIn) then
  869.     Exit;
  870.   FLocalSocket:= socket(PF_INET, FType, 0);
  871.   if FLocalSocket = INVALID_SOCKET then
  872.     begin
  873.       SocketError(WSAGetLastError);
  874.       Exit;
  875.     end;
  876.   EventMask:= (FD_CONNECT or FD_READ or FD_CLOSE);
  877.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  878.     begin
  879.       SocketError(WSAGetLastError);
  880.       closesocket(FLocalSocket);
  881.       Exit;
  882.     end;
  883.   SockOpt:= true; {Enable OOB Data inline}
  884.   if setsockopt(FLocalSocket, SOL_SOCKET, SO_OOBINLINE, PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then
  885.     begin
  886.       SocketError(WSAGetLastError);
  887.       closesocket(FLocalSocket);
  888.       Exit;
  889.     end;
  890.   if connect(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  891.     begin
  892.       if WSAGetLastError <> WSAEWOULDBLOCK then
  893.         begin
  894.           SocketError(WSAGetLastError);
  895.           closesocket(FLocalSocket);
  896.           Exit;
  897.         end;
  898.     end;
  899.   FSocketState:= ssOpen;
  900. end;
  901. procedure TTCPClient.Close;
  902. begin
  903.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  904.     Exit;
  905.   SocketClose(FLocalSocket, FHandle);
  906.   if FLocalSocket = INVALID_SOCKET then
  907.     FSocketState:= ssClosed;
  908. end;
  909. procedure TTCPClient.Write(Data: string);
  910. begin
  911.   SocketWrite(FLocalSocket, 0, Data);
  912. end;
  913. function TTCPClient.Read: string;
  914. begin
  915.   Result:= SocketRead(FLocalSocket, 0);
  916. end;
  917. function TTCPClient.Peek: string;
  918. begin
  919.   Result:= SocketRead(FLocalSocket, MSG_PEEK);
  920. end;
  921. function TTCPClient.WriteBuffer(Buffer: Pointer; Size: integer): integer;
  922. begin
  923.   Result:= SocketWriteBuffer(FLocalSocket, Buffer, Size, 0);
  924. end;
  925. function TTCPClient.ReadBuffer(Buffer: Pointer; Size: integer): integer;
  926. begin
  927.   Result:= SocketReadBuffer(FLocalSocket, Buffer, Size, 0);
  928. end;
  929. function TTCPClient.GetPeerAddress: string;
  930. begin
  931.   Result:= PeerToAddress(FLocalSocket);
  932. end;
  933. function TTCPClient.GetPeerPort: string;
  934. begin
  935.   Result:= PeerToPort(FLocalSocket);
  936. end;
  937. (**** TTCPServer Class ****)
  938. constructor TTCPServer.Create(AOwner: TComponent);
  939. begin
  940.   inherited Create(AOwner);
  941.   FHandle:= AllocateHWnd(WndProc);
  942.   FProtocol:= IPPROTO_TCP;
  943.   FType:= SOCK_STREAM;
  944.   FClients:= TClientList.Create;
  945. end;
  946. destructor TTCPServer.Destroy;
  947. begin
  948.   Close;
  949.   DeallocateHWnd(FHandle);
  950.   FClients.Free;
  951.   inherited Destroy;
  952. end;
  953. procedure TTCPServer.OpenConnection(Socket: TSocket; Error: word);
  954. var
  955.   Len: integer;
  956.   NewSocket: TSocket;
  957.   SockAddrIn: TSockAddrIn;
  958.   SockOpt: LongBool;
  959.   EventMask: longint;
  960. begin
  961.   if Error <> 0 then
  962.     SocketError(Error)
  963.   else
  964.     begin
  965.       Len:= SizeOf(SockAddrIn);
  966.       {$IFDEF VER140} // Delphi 6
  967.      
  968.            NewSocket:= accept(FLocalSocket, SockAddrIn, Len);
  969.       {$ELSE}         // Delphi 2
  970.       NewSocket:= accept(FLocalSocket, @SockAddrIn, @Len);
  971.       {$ENDIF}
  972.       if NewSocket = INVALID_SOCKET then
  973.         begin
  974.           SocketError(WSAGetLastError);
  975.           Exit;
  976.         end;
  977.       EventMask:= (FD_READ or FD_CLOSE);
  978.       if WSAASyncSelect(NewSocket, FHandle, WM_ASYNCSELECT, EventMask) <> 0 then
  979.         begin
  980.           SocketError(WSAGetLastError);
  981.           closesocket(NewSocket);
  982.           Exit;
  983.         end;
  984.       SockOpt:= true; {Enable OOB Data inline}
  985.       if setsockopt(NewSocket, SOL_SOCKET, SO_OOBINLINE , PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then
  986.         begin
  987.           SocketError(WSAGetLastError);
  988.           closesocket(NewSocket);
  989.           Exit;
  990.         end;
  991.       if not FClients.Add(NewSocket) then
  992.         SocketClose(NewSocket, FHandle)
  993.       else
  994.         if Assigned(FOnAccept) then
  995.           FOnAccept(Self, NewSocket);
  996.     end;
  997. end;
  998. procedure TTCPServer.CloseConnection(Socket: TSocket; Error: word);
  999. begin
  1000.   if Error = WSAENETDOWN then
  1001.     SocketError(Error)
  1002.   else
  1003.     begin
  1004.       if Assigned(FOnClose) then
  1005.         FOnClose(Self, Socket);
  1006.       Disconnect(Socket);
  1007.     end;
  1008. end;
  1009. procedure TTCPServer.IncommingData(Socket: TSocket; Error: word);
  1010. begin
  1011.   if Error <> 0 then
  1012.     SocketError(Error)
  1013.   else
  1014.     if Assigned(FOnData) then
  1015.       FOnData(Self, Socket);
  1016. end;
  1017. procedure TTCPServer.WndProc(var AMsg: TMessage);
  1018. var
  1019.   Error: word;
  1020. begin
  1021.   with AMsg do
  1022.     case Msg of
  1023.       WM_ASYNCSELECT:
  1024.         begin
  1025.           if (FSocketState = ssClosed) then
  1026.             Exit;
  1027.           Error:= WSAGetSelectError(LParam);
  1028.           case WSAGetSelectEvent(LParam) of
  1029.             FD_READ  : IncommingData(WParam, Error);
  1030.             FD_ACCEPT: OpenConnection(WParam, Error);
  1031.             FD_CLOSE : CloseConnection(WParam, Error);
  1032.           else
  1033.             if Error <> 0 then
  1034.               SocketError(Error);
  1035.           end;
  1036.         end;
  1037.     else
  1038.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  1039.     end;
  1040. end;
  1041. procedure TTCPServer.Open;
  1042. var
  1043.   SockAddrIn: TSockAddrIn;
  1044. begin
  1045.   if (FSocketState <> ssClosed) then
  1046.     Exit;
  1047.   if not GetAnySockAddrIn(FPort, SockAddrIn) then
  1048.     Exit;
  1049.   FLocalSocket:= socket(PF_INET, FType, 0);
  1050.   if FLocalSocket = INVALID_SOCKET then
  1051.     begin
  1052.       SocketError(WSAGetLastError);
  1053.       Exit;
  1054.     end;
  1055.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, FD_ACCEPT) <> 0 then
  1056.     begin
  1057.       SocketError(WSAGetLastError);
  1058.       closesocket(FLocalSocket);
  1059.       Exit;
  1060.     end;
  1061.   if bind(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  1062.     begin
  1063.       SocketError(WSAGetLastError);
  1064.       closesocket(FLocalSocket);
  1065.       Exit;
  1066.     end;
  1067.   if listen(FLocalSocket, 5) <> 0 then
  1068.     begin
  1069.       SocketError(WSAGetLastError);
  1070.       closesocket(FLocalSocket);
  1071.       Exit;
  1072.     end;
  1073.   FSocketState:= ssListening;
  1074. end;
  1075. procedure TTCPServer.Close;
  1076. var
  1077.   i: integer;
  1078.   Dummy: TSocket;
  1079. begin
  1080.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  1081.     Exit;
  1082.   for i:= 0 to FClients.Count-1 do
  1083.     begin
  1084.       Dummy:= FClients[i];
  1085.       SocketClose(Dummy, FHandle);
  1086.     end;
  1087.   FClients.Clear;
  1088.   SocketClose(FLocalSocket, FHandle);
  1089.   if FLocalSocket = INVALID_SOCKET then
  1090.     FSocketState:= ssClosed;
  1091. end;
  1092. procedure TTCPServer.Write(Socket: TSocket; Data: string);
  1093. begin
  1094.   SocketWrite(Socket, 0, Data);
  1095. end;
  1096. function TTCPServer.Read(Socket: TSocket): string;
  1097. begin
  1098.   Result:= SocketRead(Socket, 0);
  1099. end;
  1100. function TTCPServer.Peek(Socket: TSocket): string;
  1101. begin
  1102.   Result:= SocketRead(Socket, MSG_PEEK);
  1103. end;
  1104. function TTCPServer.WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  1105. begin
  1106.   Result:= SocketWriteBuffer(Socket, Buffer, Size, 0);
  1107. end;
  1108. function TTCPServer.ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
  1109. begin
  1110.   Result:= SocketReadBuffer(Socket, Buffer, Size, 0);
  1111. end;
  1112. procedure TTCPServer.Disconnect(Socket: TSocket);
  1113. begin
  1114.   FClients.Delete(Socket);
  1115.   SocketClose(Socket, FHandle);
  1116. end;
  1117. (**** TUDPClient Class ****)
  1118. constructor TUDPClient.Create(AOwner: TComponent);
  1119. begin
  1120.   inherited Create(AOwner);
  1121.   FHandle:= AllocateHWnd(WndProc);
  1122.   FProtocol:= IPPROTO_UDP;
  1123.   FType:= SOCK_DGRAM;
  1124. end;
  1125. destructor TUDPClient.Destroy;
  1126. begin
  1127.   Close;
  1128.   DeallocateHWnd(FHandle);
  1129.   inherited Destroy;
  1130. end;
  1131. procedure TUDPClient.IncommingData(Socket: TSocket; Error: word);
  1132. begin
  1133.   if Error <> 0 then
  1134.     SocketError(Error)
  1135.   else
  1136.     if Assigned(FOnData) then
  1137.       FOnData(Self, Socket);
  1138. end;
  1139. procedure TUDPClient.WndProc(var AMsg: TMessage);
  1140. var
  1141.   Error: word;
  1142. begin
  1143.   with AMsg do
  1144.     case Msg of
  1145.       WM_ASYNCSELECT:
  1146.         begin
  1147.           if (FSocketState = ssClosed) then
  1148.             Exit;
  1149.           Error:= WSAGetSelectError(LParam);
  1150.           case WSAGetSelectEvent(LParam) of
  1151.             FD_READ   : IncommingData(WParam, Error);
  1152.           else
  1153.             if Error <> 0 then
  1154.               SocketError(Error);
  1155.           end;
  1156.         end;
  1157.     else
  1158.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  1159.     end;
  1160. end;
  1161. procedure TUDPClient.Open;
  1162. var
  1163.   SockAddrIn: TSockAddrIn;
  1164. begin
  1165.   if (FSocketState <> ssClosed) then
  1166.     Exit;
  1167.   if not GetSockAddrIn(FHost, FPort, SockAddrIn) then
  1168.     Exit;
  1169.   FLocalSocket:= socket(PF_INET, FType, 0);
  1170.   if FLocalSocket = INVALID_SOCKET then
  1171.     begin
  1172.       SocketError(WSAGetLastError);
  1173.       Exit;
  1174.     end;
  1175.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, FD_READ) <> 0 then
  1176.     begin
  1177.       SocketError(WSAGetLastError);
  1178.       closesocket(FLocalSocket);
  1179.       Exit;
  1180.     end;
  1181.   if connect(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  1182.     begin
  1183.       if WSAGetLastError <> WSAEWOULDBLOCK then
  1184.         begin
  1185.           SocketError(WSAGetLastError);
  1186.           closesocket(FLocalSocket);
  1187.           Exit;
  1188.         end;
  1189.     end;
  1190.   FSocketState:= ssOpen;
  1191. end;
  1192. procedure TUDPClient.Close;
  1193. begin
  1194.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  1195.     Exit;
  1196.   SocketClose(FLocalSocket, FHandle);
  1197.   if FLocalSocket = INVALID_SOCKET then
  1198.     FSocketState:= ssClosed;
  1199. end;
  1200. procedure TUDPClient.Write(Data: string);
  1201. begin
  1202.   SocketWrite(FLocalSocket, 0, Data);
  1203. end;
  1204. function TUDPClient.Read: string;
  1205. begin
  1206.   Result:= SocketRead(FLocalSocket, 0);
  1207. end;
  1208. function TUDPClient.Peek: string;
  1209. begin
  1210.   Result:= SocketRead(FLocalSocket, MSG_PEEK);
  1211. end;
  1212. function TUDPClient.WriteBuffer(Buffer: Pointer; Size: integer): integer;
  1213. begin
  1214.   Result:= SocketWriteBuffer(FLocalSocket, Buffer, Size, 0);
  1215. end;
  1216. function TUDPClient.ReadBuffer(Buffer: Pointer; Size: integer): integer;
  1217. begin
  1218.   Result:= SocketReadBuffer(FLocalSocket, Buffer, Size, 0);
  1219. end;
  1220. function TUDPClient.GetPeerAddress: string;
  1221. begin
  1222.   Result:= PeerToAddress(FLocalSocket);
  1223. end;
  1224. function TUDPClient.GetPeerPort: string;
  1225. begin
  1226.   Result:= PeerToPort(FLocalSocket);
  1227. end;
  1228. (**** TUDPServer Class ****)
  1229. constructor TUDPServer.Create(AOwner: TComponent);
  1230. begin
  1231.   inherited Create(AOwner);
  1232.   FHandle:= AllocateHWnd(WndProc);
  1233.   FProtocol:= IPPROTO_UDP;
  1234.   FType:= SOCK_DGRAM;
  1235. end;
  1236. destructor TUDPServer.Destroy;
  1237. begin
  1238.   Close;
  1239.   DeallocateHWnd(FHandle);
  1240.   inherited Destroy;
  1241. end;
  1242. procedure TUDPServer.IncommingData(Socket: TSocket; Error: word);
  1243. begin
  1244.   if Error <> 0 then
  1245.     SocketError(Error)
  1246.   else
  1247.     if Assigned(FOnData) then
  1248.       FOnData(Self, Socket);
  1249. end;
  1250. procedure TUDPServer.WndProc(var AMsg: TMessage);
  1251. var
  1252.   Error: word;
  1253. begin
  1254.   with AMsg do
  1255.     case Msg of
  1256.       WM_ASYNCSELECT:
  1257.         begin
  1258.           if (FSocketState = ssClosed) then
  1259.             Exit;
  1260.           Error:= WSAGetSelectError(LParam);
  1261.           case WSAGetSelectEvent(LParam) of
  1262.             FD_READ  : IncommingData(WParam, Error);
  1263.           else
  1264.             if Error <> 0 then
  1265.               SocketError(Error);
  1266.           end;
  1267.         end;
  1268.     else
  1269.       Result:= DefWindowProc(FHandle, Msg, WParam, LParam);
  1270.     end;
  1271. end;
  1272. procedure TUDPServer.Open;
  1273. var
  1274.   SockAddrIn: TSockAddrIn;
  1275.   SockOpt: LongBool;
  1276. begin
  1277.   if (FSocketState <> ssClosed) then
  1278.     Exit;
  1279.   if not GetAnySockAddrIn(FPort, SockAddrIn) then
  1280.     Exit;
  1281.   FLocalSocket:= socket(PF_INET, FType, 0);
  1282.   if FLocalSocket = INVALID_SOCKET then
  1283.     begin
  1284.       SocketError(WSAGetLastError);
  1285.       Exit;
  1286.     end;
  1287.   if WSAASyncSelect(FLocalSocket, FHandle, WM_ASYNCSELECT, FD_READ) <> 0 then
  1288.     begin
  1289.       SocketError(WSAGetLastError);
  1290.       closesocket(FLocalSocket);
  1291.       Exit;
  1292.     end;
  1293.   SockOpt:= true; {Enable Broadcasting on this Socket}
  1294.   if setsockopt(FLocalSocket, SOL_SOCKET, SO_BROADCAST, PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then
  1295.     begin
  1296.       SocketError(WSAGetLastError);
  1297.       closesocket(FLocalSocket);
  1298.       Exit;
  1299.     end;
  1300.   if bind(FLocalSocket, SockAddrIn, SizeOf(SockAddrIn)) <> 0 then
  1301.     begin
  1302.       SocketError(WSAGetLastError);
  1303.       closesocket(FLocalSocket);
  1304.       Exit;
  1305.     end;
  1306.   FSocketState:= ssListening;
  1307. end;
  1308. procedure TUDPServer.Close;
  1309. begin
  1310.   if (FSocketState = ssNotStarted) or (FSocketState = ssClosed) then
  1311.     Exit;
  1312.   SocketClose(FLocalSocket, FHandle);
  1313.   if FLocalSocket = INVALID_SOCKET then
  1314.     FSocketState:= ssClosed;
  1315. end;
  1316. procedure TUDPServer.Write(Socket: TSocket; Data: string; var SockAddrIn: TSockAddrIn);
  1317. begin
  1318.   SocketWriteTo(Socket, 0, Data, SockAddrIn);
  1319. end;
  1320. function TUDPServer.Read(Socket: TSocket; var SockAddrIn: TSockAddrIn): string;
  1321. begin
  1322.   Result:= SocketReadFrom(Socket, 0, SockAddrIn);
  1323. end;
  1324. function TUDPServer.Peek(Socket: TSocket; var SockAddrIn: TSockAddrIn): string;
  1325. begin
  1326.   Result:= SocketReadFrom(Socket, MSG_PEEK, SockAddrIn);
  1327. end;
  1328. function TUDPServer.WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer; var SockAddrIn: TSockAddrIn): integer;
  1329. begin
  1330.   Result:= SocketWriteBufferTo(Socket, Buffer, Size, 0, SockAddrIn);
  1331. end;
  1332. function TUDPServer.ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer; var SockAddrIn: TSockAddrIn): integer;
  1333. begin
  1334.   Result:= SocketReadBufferFrom(Socket, Buffer, Size, 0, SockAddrIn);
  1335. end;
  1336. end.