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

Delphi控件源码

开发平台:

Delphi

  1. {
  2.   Delphi Winsock 1.1 Library by Aphex
  3.   http://iamaphex.cjb.net
  4.   unremote@knology.net
  5. }
  6. unit SocketUnit;
  7. interface
  8. uses Windows, Winsock;
  9. type
  10.   TTransferCallback = procedure(BytesTotal: dword; BytesDone: dword);
  11.   TClientSocket = class(TObject)
  12.   private
  13.     FAddress: pchar;
  14.     FData: pointer;
  15.     FTag: integer;
  16.     FConnected: boolean;
  17.     function GetLocalAddress: string;
  18.     function GetLocalPort: integer;
  19.     function GetRemoteAddress: string;
  20.     function GetRemotePort: integer;
  21.   protected
  22.     FSocket: TSocket;
  23.   public
  24.     procedure Connect(Address: string; Port: integer);
  25.     property Connected: boolean read FConnected;
  26.     property Data: pointer read FData write FData;
  27.     destructor Destroy; override;
  28.     procedure Disconnect;
  29.     procedure Idle(Seconds: integer);
  30.     property LocalAddress: string read GetLocalAddress;
  31.     property LocalPort: integer read GetLocalPort;
  32.     function ReceiveBuffer(var Buffer; BufferSize: integer): integer;
  33.     procedure ReceiveFile(FileName: string; TransferCallback: TTransferCallback);
  34.     function ReceiveLength: integer;
  35.     function ReceiveString: string;
  36.     property RemoteAddress: string read GetRemoteAddress;
  37.     property RemotePort: integer read GetRemotePort;
  38.     function SendBuffer(var Buffer; BufferSize: integer): integer;
  39.     procedure SendFile(FileName: string; TransferCallback: TTransferCallback);
  40.     function SendString(const Buffer: string): integer;
  41.     property Socket: TSocket read FSocket;
  42.     property Tag: integer read FTag write FTag;
  43.   end;
  44.   TServerSocket = class(TObject)
  45.   private
  46.     FListening: boolean;
  47.     function GetLocalAddress: string;
  48.     function GetLocalPort: integer;
  49.   protected
  50.     FSocket: TSocket;
  51.   public
  52.     function Accept: TClientSocket;
  53.     destructor Destroy; override;
  54.     procedure Disconnect;
  55.     procedure Idle;
  56.     procedure Listen(Port: integer);
  57.     property Listening: boolean read FListening;
  58.     property LocalAddress: string read GetLocalAddress;
  59.     property LocalPort: integer read GetLocalPort;
  60.   end;
  61. var
  62.   WSAData: TWSAData;
  63. implementation
  64. procedure TClientSocket.Connect(Address: string; Port: integer);
  65. var
  66.   SockAddrIn: TSockAddrIn;
  67.   HostEnt: PHostEnt;
  68. begin
  69.   Disconnect;
  70.   FAddress := pchar(Address);
  71.   FSocket := Winsock.socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  72.   SockAddrIn.sin_family := AF_INET;
  73.   SockAddrIn.sin_port := htons(Port);
  74.   SockAddrIn.sin_addr.s_addr := inet_addr(FAddress);
  75.   if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
  76.   begin
  77.     HostEnt := gethostbyname(FAddress);
  78.     if HostEnt = nil then
  79.     begin
  80.       Exit;
  81.     end;
  82.     SockAddrIn.sin_addr.s_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
  83.   end;
  84.   Winsock.Connect(FSocket, SockAddrIn, SizeOf(SockAddrIn));
  85.   FConnected := True;
  86. end;
  87. procedure TClientSocket.Disconnect;
  88. begin
  89.   closesocket(FSocket);
  90.   FConnected := False;
  91. end;
  92. function TClientSocket.GetLocalAddress: string;
  93. var
  94.   SockAddrIn: TSockAddrIn;
  95.   Size: integer;
  96. begin
  97.   Size := sizeof(SockAddrIn);
  98.   getsockname(FSocket, SockAddrIn, Size);
  99.   Result := inet_ntoa(SockAddrIn.sin_addr);
  100. end;
  101. function TClientSocket.GetLocalPort: integer;
  102. var
  103.   SockAddrIn: TSockAddrIn;
  104.   Size: Integer;
  105. begin
  106.   Size := sizeof(SockAddrIn);
  107.   getsockname(FSocket, SockAddrIn, Size);
  108.   Result := ntohs(SockAddrIn.sin_port);
  109. end;
  110. function TClientSocket.GetRemoteAddress: string;
  111. var
  112.   SockAddrIn: TSockAddrIn;
  113.   Size: Integer;
  114. begin
  115.   Size := sizeof(SockAddrIn);
  116.   getpeername(FSocket, SockAddrIn, Size);
  117.   Result := inet_ntoa(SockAddrIn.sin_addr);
  118. end;
  119. function TClientSocket.GetRemotePort: integer;
  120. var
  121.   SockAddrIn: TSockAddrIn;
  122.   Size: Integer;
  123. begin
  124.   Size := sizeof(SockAddrIn);
  125.   getpeername(FSocket, SockAddrIn, Size);
  126.   Result := ntohs(SockAddrIn.sin_port);
  127. end;
  128. procedure TClientSocket.Idle(Seconds: integer);
  129. var
  130.   FDset: TFDset;
  131.   TimeVal: TTimeVal;
  132. begin
  133.   if Seconds = 0 then
  134.   begin
  135.     FD_ZERO(FDSet);
  136.     FD_SET(FSocket, FDSet);
  137.     select(0, @FDset, nil, nil, nil);
  138.   end
  139.   else
  140.   begin
  141.     TimeVal.tv_sec := Seconds;
  142.     TimeVal.tv_usec := 0;
  143.     FD_ZERO(FDSet);
  144.     FD_SET(FSocket, FDSet);
  145.     select(0, @FDset, nil, nil, @TimeVal);
  146.   end;
  147. end;
  148. function TClientSocket.ReceiveLength: integer;
  149. begin
  150.   Result := ReceiveBuffer(pointer(nil)^, -1);
  151. end;
  152. function TClientSocket.ReceiveBuffer(var Buffer; BufferSize: integer): integer;
  153. begin
  154.   if BufferSize = -1 then
  155.   begin
  156.     if ioctlsocket(FSocket, FIONREAD, Longint(Result)) = SOCKET_ERROR then
  157.     begin
  158.       Result := SOCKET_ERROR;
  159.       Disconnect;
  160.     end;
  161.   end
  162.   else
  163.   begin
  164.      Result := recv(FSocket, Buffer, BufferSize, 0);
  165.      if Result = 0 then
  166.      begin
  167.        Disconnect;
  168.      end;
  169.      if Result = SOCKET_ERROR then
  170.      begin
  171.        Result := WSAGetLastError;
  172.        if Result = WSAEWOULDBLOCK then
  173.        begin
  174.          Result := 0;
  175.        end
  176.        else
  177.        begin
  178.          Disconnect;
  179.        end;
  180.      end;
  181.   end;
  182. end;
  183. function TClientSocket.ReceiveString: string;
  184. begin
  185.   SetLength(Result, ReceiveBuffer(pointer(nil)^, -1));
  186.   SetLength(Result, ReceiveBuffer(pointer(Result)^, Length(Result)));
  187. end;
  188. procedure TClientSocket.ReceiveFile(FileName: string; TransferCallback: TTransferCallback);
  189. var
  190.   BinaryBuffer: pchar;
  191.   BinaryFile: THandle;
  192.   BinaryFileSize, BytesReceived, BytesWritten, BytesDone: dword;
  193. begin
  194.   BytesDone := 0;
  195.   BinaryFile := CreateFile(pchar(FileName), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  196.   Idle(0);
  197.   ReceiveBuffer(BinaryFileSize, sizeof(BinaryFileSize));
  198.   while BytesDone < BinaryFileSize do
  199.   begin
  200.     Sleep(1);
  201.     BytesReceived := ReceiveLength;
  202.     if BytesReceived > 0 then
  203.     begin
  204.       GetMem(BinaryBuffer, BytesReceived);
  205.       try
  206.         ReceiveBuffer(BinaryBuffer^, BytesReceived);
  207.         WriteFile(BinaryFile, BinaryBuffer^, BytesReceived, BytesWritten, nil);
  208.         Inc(BytesDone, BytesReceived);
  209.         if Assigned(TransferCallback) then TransferCallback(BinaryFileSize, BytesDone);
  210.       finally
  211.         FreeMem(BinaryBuffer);
  212.       end;
  213.     end;
  214.   end;
  215.   CloseHandle(BinaryFile);
  216. end;
  217. procedure TClientSocket.SendFile(FileName: string; TransferCallback: TTransferCallback);
  218. var
  219.   BinaryFile: THandle;
  220.   BinaryBuffer: pchar;
  221.   BinaryFileSize, BytesRead, BytesDone: dword;
  222. begin
  223.   BytesDone := 0;
  224.   BinaryFile := CreateFile(pchar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  225.   BinaryFileSize := GetFileSize(BinaryFile, nil);
  226.   SendBuffer(BinaryFileSize, sizeof(BinaryFileSize));
  227.   GetMem(BinaryBuffer, 2048);
  228.   try
  229.     repeat
  230.       Sleep(1);
  231.       ReadFile(BinaryFile, BinaryBuffer^, 2048, BytesRead, nil);
  232.       Inc(BytesDone, BytesRead);
  233.       repeat
  234.         Sleep(1);
  235.       until SendBuffer(BinaryBuffer^, BytesRead) <> -1;
  236.       if Assigned(TransferCallback) then TransferCallback(BinaryFileSize, BytesDone);
  237.     until BytesRead < 2048;
  238.   finally
  239.     FreeMem(BinaryBuffer);
  240.   end;
  241.   CloseHandle(BinaryFile);
  242. end;
  243. function TClientSocket.SendBuffer(var Buffer; BufferSize: integer): integer;
  244. var
  245.   ErrorCode: integer;
  246. begin
  247.   Result := send(FSocket, Buffer, BufferSize, 0);
  248.   if Result = SOCKET_ERROR then
  249.   begin
  250.     ErrorCode := WSAGetLastError;
  251.     if (ErrorCode = WSAEWOULDBLOCK) then
  252.     begin
  253.       Result := -1;
  254.     end
  255.     else
  256.     begin
  257.       Disconnect;
  258.     end;
  259.   end;
  260. end;
  261. function TClientSocket.SendString(const Buffer: string): integer;
  262. begin
  263.   Result := SendBuffer(pointer(Buffer)^, Length(Buffer));
  264. end;
  265. destructor TClientSocket.Destroy;
  266. begin
  267.   inherited Destroy;
  268.   Disconnect;
  269. end;
  270. procedure TServerSocket.Listen(Port: integer);
  271. var
  272.   SockAddrIn: TSockAddrIn;
  273. begin
  274.   Disconnect;
  275.   FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  276.   SockAddrIn.sin_family := AF_INET;
  277.   SockAddrIn.sin_addr.s_addr := INADDR_ANY;
  278.   SockAddrIn.sin_port := htons(Port);
  279.   bind(FSocket, SockAddrIn, sizeof(SockAddrIn));
  280.   FListening := True;
  281.   Winsock.listen(FSocket, 5);
  282. end;
  283. function TServerSocket.GetLocalAddress: string;
  284. var
  285.   SockAddrIn: TSockAddrIn;
  286.   Size: integer;
  287. begin
  288.   Size := sizeof(SockAddrIn);
  289.   getsockname(FSocket, SockAddrIn, Size);
  290.   Result := inet_ntoa(SockAddrIn.sin_addr);
  291. end;
  292. function TServerSocket.GetLocalPort: integer;
  293. var
  294.   SockAddrIn: TSockAddrIn;
  295.   Size: Integer;
  296. begin
  297.   Size := sizeof(SockAddrIn);
  298.   getsockname(FSocket, SockAddrIn, Size);
  299.   Result := ntohs(SockAddrIn.sin_port);
  300. end;
  301. procedure TServerSocket.Idle;
  302. var
  303.   FDset: TFDset;
  304. begin
  305.   FD_ZERO(FDSet);
  306.   FD_SET(FSocket, FDSet);
  307.   select(0, @FDset, nil, nil, nil);
  308. end;
  309. function TServerSocket.Accept: TClientSocket;
  310. var
  311.   Size: integer;
  312.   SockAddr: TSockAddr;
  313. begin
  314.   Result := TClientSocket.Create;
  315.   Size := sizeof(TSockAddr);
  316.   Result.FSocket := Winsock.accept(FSocket, @SockAddr, @Size);
  317.   if Result.FSocket = INVALID_SOCKET then
  318.   begin
  319.     Disconnect;
  320.   end
  321.   else
  322.   begin
  323.     Result.FConnected := True;
  324.   end;
  325. end;
  326. procedure TServerSocket.Disconnect;
  327. begin
  328.   FListening := False;
  329.   closesocket(FSocket);
  330. end;
  331. destructor TServerSocket.Destroy;
  332. begin
  333.   inherited Destroy;
  334.   Disconnect;
  335. end;
  336. initialization
  337.   WSAStartUp(257, WSAData);
  338. finalization
  339.   WSACleanup;
  340. end.