⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psisockethandle.pas

📁 一个delphi的p2p控件的源代码
💻 PAS
字号:
unit PsiSocketHandle;

//******************************************************************************
// The original software is under
// Copyright (c) 1993 - 2000, Chad Z. Hower (Kudzu)
//   and the Indy Pit Crew - http://www.nevrona.com/Indy/
//
// Amended : November 2000, by Michael M. Michalak MACS for use with
// MorphTek.com Inc Peer to Peer Open Source Components - http://www.morphtek.com
//
//******************************************************************************

interface

uses
  Classes,
  PsiGlobal,
  PsiStack, PsiStackConsts;

type
  TPsiSocketHandle = class;

  TPsiSocketHandles = class(TOwnedCollection)
  protected
    FDefaultPort: integer;
    //
    function GetItem(Index: Integer): TPsiSocketHandle;
    procedure SetItem(Index: Integer; const Value: TPsiSocketHandle);
  public
  	constructor Create(AOwner: TComponent); reintroduce;
    function add: TPsiSocketHandle; reintroduce;
    property Items[Index: Integer]: TPsiSocketHandle read GetItem write SetItem; default;
    //
    property DefaultPort: integer read FDefaultPort write FDefaultPort;
  end;

  TPsiSocketHandle = class(TCollectionItem)
  protected
    FHandle: TPsiStackSocketHandle;
    FHandleAllocated: Boolean;
    FIP, FPeerIP: string;
    FPort, FPeerPort: integer;
  public
    procedure Accept(ASocket: TPsiStackSocketHandle; var VIP: string; var VPort: Integer);
    procedure AllocateSocket(const ASocketType: Integer = Psi_SOCK_STREAM;
     const AProtocol: Integer = Psi_IPPROTO_IP);
		// Returns True if error was ignored (Matches iIgnore), false if no error occurred
    procedure Assign(Source: TPersistent); override;
    procedure Bind;
    procedure CloseSocket; virtual;
    function Connect(const AFamily: Integer = Psi_PF_INET): Integer; virtual;
    constructor Create(ACollection: TCollection); override;
    destructor Destroy; override;
    procedure Listen(const anQueueCount: integer = 5);
    function Readable(AMSec: Integer = PsiTimeoutDefault): boolean;
    function Recv(var ABuf; ALen, AFlags: Integer): Integer;
    function RecvFrom(var ABuffer; const ALength, AFlags: Integer; var VIP: string;
     var VPort: Integer): Integer; virtual;
    function Send(var Buf; len, flags: Integer): Integer;
		procedure SendTo(const AIP: string; const APort: Integer; var ABuffer;
     const ABufferSize: Integer);
    procedure SetPeer(const asIP: string; anPort: integer);
    function SetSockOpt(level, optname: Integer; optval: PChar; optlen: Integer): Integer;
    //
    property HandleAllocated: Boolean read FHandleAllocated;
    property Handle: TPsiStackSocketHandle read FHandle;
  	property PeerIP: string read FPeerIP;
    property PeerPort: integer read FPeerPort;
  published
  	property IP: string read FIP write FIP;
    property Port: integer read FPort write FPort;
  end;

implementation

uses
  PsiAntiFreezeBase,
  PsiComponent, PsiException,
  PsiResourceStrings;

{ TPsiSocketHandle }

procedure TPsiSocketHandle.AllocateSocket(const ASocketType: Integer = Psi_SOCK_STREAM;
 const AProtocol: Integer = Psi_IPPROTO_IP);
begin
	// If we are reallocating a socket - close and destroy the old socket handle
 	CloseSocket;
  FHandle := GStack.CreateSocketHandle(ASocketType, AProtocol);
	FHandleAllocated := True;
end;

procedure TPsiSocketHandle.CloseSocket;
begin
	if HandleAllocated then begin
    // Must be first, closing socket will trigger some errors, and they
    // may then check (in other threads) Connected, which checks this.
    FHandleAllocated := False;
    GStack.WSCloseSocket(Handle);
    FHandle := Psi_INVALID_SOCKET;
  end;
end;

function TPsiSocketHandle.Connect(const AFamily: Integer = Psi_PF_INET): Integer;
begin
	result := GStack.WSConnect(Handle, AFamily, IP, Port);
end;

destructor TPsiSocketHandle.Destroy;
begin
	CloseSocket;
  inherited;
end;

function TPsiSocketHandle.Recv(var ABuf; ALen, AFlags: Integer): Integer;
begin
  result := GStack.WSRecv(Handle, ABuf, ALen, AFlags);
end;

function TPsiSocketHandle.Send(var Buf; len, flags: Integer): Integer;
begin
	result := GStack.WSSend(Handle, Buf, len, flags);
end;

function TPsiSocketHandle.SetSockOpt(level, optname: Integer; optval: PChar;
  optlen: Integer): Integer;
begin
  result := GStack.WSSetSockOpt(Handle, level, optname, optval, optlen);
end;

procedure TPsiSocketHandle.SendTo(const AIP: string; const APort: Integer; var ABuffer;
 const ABufferSize: Integer);
var
	BytesOut: Integer;
begin
  BytesOut := GStack.WSSendTo(Handle, ABuffer, ABufferSize, 0, AIP, APort);
  if BytesOut = 0 then begin
    raise EPsiException.Create(RS0BytesWereSent);
  end else if BytesOut = Psi_SOCKET_ERROR then begin
    if GStack.WSGetLastError() = Psi_WSAEMSGSIZE then begin
      raise EPsiException.Create(RSPackageSizeTooBig);
    end else begin
      GStack.CheckForSocketError;
    end;
  end else if BytesOut <> ABufferSize then begin
    raise EPsiException.Create(RSNotAllBytesSent);
  end;
end;

function TPsiSocketHandle.RecvFrom(var ABuffer; const ALength, AFlags: Integer; var VIP: string;
 var VPort: Integer): Integer;
begin
  result := GStack.WSRecvFrom(Handle, ABuffer, ALength, AFlags, VIP, VPort);
end;

procedure TPsiSocketHandle.Bind;
begin
  if GStack.CheckForSocketError(GStack.WSBind(Handle, Psi_PF_INET, IP, Port), [Psi_WSAEADDRINUSE])
   then begin
    raise EPsiException.Create(RSCouldNotBindSocket);
  end;
end;

procedure TPsiSocketHandle.SetPeer(const asIP: string; anPort: integer);
begin
	FPeerIP := asIP;
  FPeerPort := anPort;
end;

procedure TPsiSocketHandle.Listen(const anQueueCount: integer);
begin
  GStack.CheckForSocketError(GStack.WSListen(Handle, anQueueCount));
end;

procedure TPsiSocketHandle.Accept(ASocket: TPsiStackSocketHandle; var VIP: string;
 var VPort: Integer);
var
  AcceptedSocket: TPsiStackSocketHandle;
begin
	AcceptedSocket := GStack.WSAccept(ASocket, VIP, VPort);
  GStack.CheckForSocketError(AcceptedSocket);
  FHandle := AcceptedSocket;
  FHandleAllocated := True;
end;

constructor TPsiSocketHandle.Create(ACollection: TCollection);
begin
  inherited;
  if assigned(ACollection) then begin
    Port := TPsiSocketHandles(ACollection).DefaultPort;
  end;
end;

function TPsiSocketHandle.Readable(AMSec: Integer): boolean;
var
  ReadList: TList;
begin
  if not FHandleAllocated then begin
     raise EPsiConnClosedGraceful.Create(RSConnectionClosedGracefully);
  end;

  if GAntiFreeze <> nil then begin
    if GAntiFreeze.Active then begin
      if AMSec = PsiTimeoutInfinite then begin
        repeat
          result := Readable(GAntiFreeze.IdleTimeOut);
        until result;
        exit;
      end else if AMSec > GAntiFreeze.IdleTimeOut then begin
        result := Readable(AMSec - GAntiFreeze.IdleTimeOut);
        if result then begin
          exit;
        end else begin
          AMSec := GAntiFreeze.IdleTimeOut;
        end;
      end;
    end;
  end;
  ReadList := TList.Create; try
    ReadList.Add(Pointer(Handle));
    Result := GStack.WSSelect(ReadList, nil, nil, AMSec) = 1;
    TPsiAntiFreezeBase.DoProcess(result = false);
  finally ReadList.free; end;
end;

procedure TPsiSocketHandle.Assign(Source: TPersistent);
var hdl : TPsiSocketHandle;
begin
  if ClassType <> Source.ClassType then
  begin
    Inherited
  end
  else
  begin
    hdl := TPsiSocketHandle(Source);
    IP := hdl.IP;
    Port := hdl.Port;
  end;
end;

{ TPsiSocketHandles }

function TPsiSocketHandles.add: TPsiSocketHandle;
begin
  result := Inherited add as TPsiSocketHandle;
  result.Port := DefaultPort;
end;

constructor TPsiSocketHandles.Create(AOwner: TComponent);
begin
  inherited Create(AOwner, TPsiSocketHandle);
end;

function TPsiSocketHandles.GetItem(Index: Integer): TPsiSocketHandle;
begin
  result := TPsiSocketHandle(inherited Items[index]);
end;

procedure TPsiSocketHandles.SetItem(Index: Integer; const Value: TPsiSocketHandle);
begin
	inherited SetItem(Index, Value);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -