📄 wsocket.pas
字号:
Feb 14, 1999 V4.00 Jump to next major version number because lots of
fundamental changes have been done. See below.
Use runtime dynamic link with winsock. All winsock functions
used by TWSocket are linked at runtime instead of loadtime. This
allows programs to run without winsock installed, provided program
doesn't try to use TWSocket or winsock function without first
checking for winsock installation.
Removed WSocketLoadWinsock and all use to DllStarted because it
is no longer necessary because winsock is automatically loaded
and initialized with the first call to a winsock function.
Added MessagePump to centralize call to the message pump.
It is a virtual procedure so that you can override it to
cutomize your message pump. Also changed slightly ProcessMessages
to closely match what is done in the forms unit.
Removed old stuff related to WaitCtrl (was already excluded from
compilation using a conditional directive).
Added NOFORMS conditional compilation to exclude the Forms unit
from wsocket. This will reduce exe or dll size by 100 to 150KB.
To use this feature, you have to add NOFORMS in your project
options in the "defines" edit box in the "directory/conditional"
tab. Then you must add a message pump to your application and
call it from TWSocket.OnMessagePump event handler. TWSocket really
need a message pump in order to receive messages from winsock.
Depending on how your application is built, you can use either
TWSocket.MessageLoop or TWSocket.ProcessMessages to quickly build
a working message pump. Or you may build your own custom message
pump taylored to your needs. Your message pump must set
TWSocket.Terminated property to TRUE when your application
terminates or you may experience long delays when closing your
application.
You may use NOFORMS setting even if you use the forms unit (GUI
application). Simply call Application.ProcessMessages in the
OnMessagePump event handler.
OnMessagePump event is not visible in the object inspector. You
must assign it at run-time before using the component and after
having created it (in a GUI application you can do that in the
FormCreate event, in a console application, you can do it right
after TWSocket.Create call).
Feb 17, 1999 V4.01 Added LineEcho and LineEdit features.
Feb 27, 1999 V4.02 Added TCustomLineWSocket.GetRcvdCount to make RcvdCount
property and ReceiveStr work in line mode.
Mar 01, 1999 V4.03 Added conditional compile for BCB4. Thanks to James
Legg <jlegg@iname.com>.
Mar 14, 1999 V4.04 Corrected a bug: wsocket hangup when there was no
OnDataAvailable handler and line mode was on.
Apr 21, 1999 V4.05 Added H+ (long strings) and X+ (extended syntax)
compilation options
May 07, 1999 V4.06 Added WSAECONNABORTED to valid error codes in TryToSend.
Jul 21, 1999 V4.07 Added GetPeerPort method, PeerPort and PeerAddr propertied
as suggested by J. Punter <JPunter@login-bv.com>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
unit WSocket;
{$B-} { Enable partial boolean evaluation }
{$T-} { Untyped pointers }
{$X+} { Enable extended syntax }
{$IFNDEF VER80} { Not for Delphi 1 }
{$H+} { Use long strings }
{$J+} { Allow typed constant to be modified }
{$ENDIF}
{$IFDEF VER110} { C++ Builder V3.0 }
{$ObjExportAll On}
{$ENDIF}
interface
uses
WinTypes, WinProcs, Messages, Classes, SysUtils,
{$IFNDEF NOFORMS} { See comments in history at 14/02/99 }
Forms,
{$ENDIF}
WSockBuf, WinSock;
const
WSocketVersion = 407;
CopyRight : String = ' TWSocket (c) 96-99 F. Piette V4.07 ';
WM_ASYNCSELECT = WM_USER + 1;
WM_ASYNCGETHOSTBYNAME = WM_USER + 2;
WM_ASYNCGETHOSTBYADDR = WM_USER + 3;
WM_TRIGGER_DATA_AVAILABLE = WM_USER + 20;
WSA_WSOCKET_TIMEOUT = 12001;
{$IFDEF WIN32}
winsocket = 'wsock32.dll'; { 32 bits TCP/IP system DLL }
{$ELSE}
winsocket = 'winsock.dll'; { 16 bits TCP/IP system DLL }
{$ENDIF}
type
ESocketException = class(Exception);
TBgExceptionEvent = procedure (Sender : TObject;
E : Exception;
var CanClose : Boolean) of object;
TSocketState = (wsInvalidState,
wsOpened, wsBound,
wsConnecting, wsConnected,
wsAccepting, wsListening,
wsClosed);
TSocketSendFlags = (wsSendNormal, wsSendUrgent);
TSocketLingerOnOff = (wsLingerOff, wsLingerOn, wsLingerNoSet);
TDataAvailable = procedure (Sender: TObject; Error: word) of object;
TDataSent = procedure (Sender: TObject; Error: word) of object;
TSessionClosed = procedure (Sender: TObject; Error: word) of object;
TSessionAvailable = procedure (Sender: TObject; Error: word) of object;
TSessionConnected = procedure (Sender: TObject; Error: word) of object;
TDnsLookupDone = procedure (Sender: TObject; Error: Word) of object;
TChangeState = procedure (Sender: TObject;
OldState, NewState : TSocketState) of object;
TDebugDisplay = procedure (Sender: TObject; var Msg : String) of object;
TWSocketSyncNextProc = procedure of object;
{$IFDEF VER110} { C++Builder V3 }
TSocket = integer;
{$ENDIF}
{$IFDEF VER120} { C++Builder V4 }
TSocket = integer;
{$ENDIF}
TCustomWSocket = class(TComponent)
private
FDnsResult : String;
FDnsResultList : TStrings;
FASocket : TSocket; { Accepted socket }
FBufList : TList;
FBufSize : Integer;
FSendFlags : Integer;
FLastError : Integer;
FWindowHandle : HWND;
FDnsLookupBuffer : array [0..MAXGETHOSTSTRUCT] of char;
FDnsLookupHandle : THandle;
{$IFDEF VER80}
FTrumpetCompability : Boolean;
{$ENDIF}
protected
FHSocket : TSocket;
FAddrStr : String;
FAddrResolved : Boolean;
FAddrFormat : Integer;
FAddrAssigned : Boolean;
FProto : integer;
FProtoAssigned : Boolean;
FProtoResolved : Boolean;
FLocalPortResolved : Boolean;
FProtoStr : String;
FPortStr : String;
FPortAssigned : Boolean;
FPortResolved : Boolean;
FPortNum : Integer;
FLocalPortStr : String;
FLocalPortNum : Integer;
FType : integer;
FLingerOnOff : TSocketLingerOnOff;
FLingerTimeout : Integer; { In seconds, 0 = disabled }
ReadLineCount : Integer;
bWrite : Boolean;
nMoreCnt : Integer;
bMoreFlag : Boolean;
nMoreMax : Integer;
bAllSent : Boolean;
FReadCount : LongInt;
FPaused : Boolean;
FCloseInvoked : Boolean;
FFlushTimeout : Integer;
FMultiThreaded : Boolean;
FState : TSocketState;
FRcvdFlag : Boolean;
FTerminated : Boolean;
FOnSessionAvailable : TSessionAvailable;
FOnSessionConnected : TSessionConnected;
FOnSessionClosed : TSessionClosed;
FOnChangeState : TChangeState;
FOnDataAvailable : TDataAvailable;
FOnDataSent : TDataSent;
FOnLineTooLong : TNotifyEvent;
FOnDnsLookupDone : TDnsLookupDone;
FOnError : TNotifyEvent;
FOnBgException : TBgExceptionEvent;
FOnDisplay : TDebugDisplay;
FOnMessagePump : TNotifyEvent;
procedure WndProc(var MsgRec: TMessage); virtual;
procedure SocketError(sockfunc: string);
procedure WMASyncSelect(var msg: TMessage); message WM_ASYNCSELECT;
procedure WMAsyncGetHostByName(var msg: TMessage); message WM_ASYNCGETHOSTBYNAME;
procedure WMAsyncGetHostByAddr(var msg: TMessage); message WM_ASYNCGETHOSTBYADDR;
procedure ChangeState(NewState : TSocketState);
procedure TryToSend;
procedure ASyncReceive(Error : Word);
procedure AssignDefaultValue; virtual;
procedure InternalClose(bShut : Boolean; Error : Word); virtual;
procedure Notification(AComponent: TComponent; operation: TOperation); override;
procedure SetSendFlags(newValue : TSocketSendFlags);
function GetSendFlags : TSocketSendFlags;
procedure SetAddr(InAddr : String);
function GetAddr : String;
procedure SetRemotePort(sPort : String); virtual;
function GetRemotePort : String;
procedure SetLocalPort(sLocalPort : String);
procedure SetProto(sProto : String); virtual;
function GetProto : String;
function GetRcvdCount : LongInt; virtual;
procedure BindSocket; virtual;
procedure SendText(Str : String);
function RealSend(Data : Pointer; Len : Integer) : Integer; virtual;
procedure RaiseExceptionFmt(const Fmt : String; args : array of const); virtual;
procedure RaiseException(const Msg : String); virtual;
procedure HandleBackGroundException(E: Exception); virtual;
procedure TriggerDisplay(Msg : String);
function TriggerDataAvailable(Error : Word) : Boolean; virtual;
procedure TriggerSessionAvailable(Error : Word); virtual;
procedure TriggerSessionConnected(Error : Word); virtual;
procedure TriggerSessionClosed(Error : Word); virtual;
procedure TriggerDataSent(Error : Word); virtual;
procedure TriggerChangeState(OldState, NewState : TSocketState); virtual;
procedure TriggerDNSLookupDone(Error : Word); virtual;
procedure TriggerError; virtual;
function DoRecv(var Buffer;
BufferSize : Integer;
Flags : Integer) : Integer; virtual;
function DoRecvFrom(FHSocket : TSocket;
var Buffer;
BufferSize : Integer;
Flags : Integer;
var From : TSockAddr;
var FromLen : Integer) : Integer; virtual;
public
sin : TSockAddrIn;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Connect; virtual;
procedure Close; virtual;
procedure Abort; virtual;
procedure Flush; virtual;
procedure WaitForClose; virtual;
procedure Listen; virtual;
function Accept: TSocket; virtual;
function Receive(Buffer : Pointer; BufferSize: integer) : integer; virtual;
function ReceiveStr : string; virtual;
function ReceiveFrom(Buffer : Pointer;
BufferSize : Integer;
var From : TSockAddr;
var FromLen : Integer) : integer; virtual;
function PeekData(Buffer : Pointer; BufferSize: integer) : integer;
function Send(Data : Pointer; Len : Integer) : integer; virtual;
function SendTo(Dest : TSockAddr;
DestLen : Integer;
Data : Pointer;
Len : Integer) : integer; virtual;
function SendStr(Str : String) : Integer; virtual;
procedure DnsLookup(HostName : String); virtual;
procedure ReverseDnsLookup(HostAddr: String); virtual;
procedure CancelDnsLookup; virtual;
function GetPeerAddr: string; virtual;
function GetPeerPort: string; virtual;
function GetPeerName(var Name : TSockAddrIn; NameLen : Integer) : integer; virtual;
function GetXPort: string; virtual;
function TimerIsSet(var tvp : TTimeVal) : Boolean; virtual;
procedure TimerClear(var tvp : TTimeVal); virtual;
function TimerCmp(var tvp : TTimeVal; var uvp : TTimeVal; IsEqual : Boolean) : Boolean; virtual;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -