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

📄 idtelnet.pas

📁 Indy控件的使用源代码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence                                   }
{ Team Coherence is Copyright 2002 by Quality Software Components      }
{                                                                      }
{ For further information / comments, visit our WEB site at            }
{ http://www.TeamCoherence.com                                         }
{**********************************************************************}
{}
{ $Log:  10371: IdTelnet.pas 
{
{   Rev 1.0    2002.11.12 10:55:40 PM  czhower
}
unit IdTelnet;

// CHANGES
//
// 26-05-2000 SG: Converted to Indy, no other change
// 13-JAN-2000 MTL: Moved to new Palette Scheme (Winshoes Servers)
//
///////////////////////////////////////////////////////////////////////////////
// Author: Mark Holmes
// ..
// This is the telnet client component. I'm still testing    {Do not Localize}
// There is no real terminal emulation other than dumb terminal
//
////////////////////////////////////////////////////////////////////////////////
{
******************************************************************************
Date        Author Change.
--------------------------------------------------------------------------------
05-Mar-2000 Mark   Added constants for telnet implememtation.
07-Mar-2000 Mark   Added a bunch of stuff... it's very much a work in progress   
03-01-2002 Andrew P.Rybin  Renamings and standardization
}

interface

uses
  Classes,
  IdException,
  IdGlobal,
  IdStack,
  IdTCPClient, IdThread,
  SysUtils;

const
  { These are the telnet command constansts from RFC 854 }
  TNC_EOR                = #239;    // End of Record RFC 885
  TNC_SE                 = #240;    // End of subnegotiation parameters.
  TNC_NOP                = #241;    // No operation.
  TNC_DATA_MARK          = #242;    // The data stream portion of a Synch.
                                    // This should always be accompanied
                                    // by a TCP Urgent notification.
  TNC_BREAK              = #243;    // NVT character BRK.
  TNC_IP                 = #244;    // The function IP.
  TNC_AO                 = #245;    // The function ABORT OUTPUT.
  TNC_AYT                = #246;    // The function ARE YOU THERE.
  TNC_EC                 = #247;    // The function ERASE CHARACTER.
  TNC_EL                 = #248;    // The function ERASE LINE.
  TNC_GA                 = #249;    // The GO AHEAD signal.
  TNC_SB                 = #250;    // Indicates that what follows is
                                    // subnegotiation of the indicated
                                    // option.
  TNC_WILL               = #251;    // Indicates the desire to begin
                                    // performing, or confirmation that
                                    // you are now performing, the
                                    // indicated option.
  TNC_WONT               = #252;    // Indicates the refusal to perform,
                                    // or continue performing, the
                                    // indicated option.
  TNC_DO                 = #253;    // Indicates the request that the
                                    // other party perform, or
                                    // confirmation that you are expecting
                                    // the other party to perform, the
                                    // indicated option.
  TNC_DONT               = #254;    // Indicates the demand that the
                                    // other party stop performing,
                                    // or confirmation that you are no
                                    // longer expecting the other party
                                    // to perform, the indicated option.
  TNC_IAC                = #255;    // Data Byte 255.

  { Telnet options from RFC 1010 }
  TNO_BINARY             = #0;      // Binary Transmission
  TNO_ECHO               = #1;      // Echo
  TNO_RECONNECT          = #2;      // Reconnection
  TNO_SGA                = #3;      // Suppress Go Ahead
  TNO_AMSN               = #4;      // Approx Message Size Negotiation
  TNO_STATUS             = #5;      // Status
  TNO_TIMING_MARK        = #6;      // Timing Mark
  TNO_RCTE               = #7;      // Remote Controlled Trans and Echo -BELL
  TNO_OLW                = #8;      // Output Line Width
  TNO_OPS                = #9;      // Output Page Size
  TNO_OCRD               = #10;     // Output Carriage-Return Disposition
  TNO_OHTS               = #11;     // Output Horizontal Tab Stops
  TNO_OHTD               = #12;     // Output Horizontal Tab Disposition
  TNO_OFD                = #13;     // Output Formfeed Disposition
  TNO_OVT                = #14;     // Output Vertical Tabstops
  TNO_OVTD               = #15;     // Output Vertical Tab Disposition
  TNO_OLD                = #16;     // Output Linefeed Disposition
  TNO_EA                 = #17;     // Extended ASCII
  TNO_LOGOUT             = #18;     // Logout
  TNO_BYTE_MACRO         = #19;     // Byte Macro
  TNO_DET                = #20;     // Data Entry Terminal
  TNO_SUPDUP             = #21;     // SUPDUP
  TNO_SUPDUP_OUTPUT      = #22;     // SUPDUP Output
  TNO_SL                 = #23;     // Send Location
  TNO_TERMTYPE           = #24;     // Terminal Type
  TNO_EOR                = #25;     // End of Record
  TNO_TACACS_ID          = #26;     // TACACS User Identification
  TNO_OM                 = #27;     // Output Marking
  TNO_TLN                = #28;     // Terminal Location Number
  TNO_3270REGIME         = #29;     // 3270 regime
  TNO_X3PAD	         = #30;     // X.3 PAD
  TNO_NAWS      	 = #31;     // Window size
  TNO_TERM_SPEED         = #32;     // Terminal speed
  TNO_RFLOW              = #33;     // Remote flow control
  TNO_LINEMODE           = #34;     // Linemode option
  TNO_XDISPLOC	         = #35;     // X Display Location
  TNO_AUTH               = #37;     // Authenticate
  TNO_ENCRYPT            = #38;     // Encryption option

  TNO_EOL                = #255;    // Extended-Options-List                               [84,JBP]

  // Sub options
  TNOS_TERM_IS           = #0;
  TNOS_TERMTYPE_SEND     = #1;      // Sub option
  TNOS_REPLY             = #2;
  TNOS_NAME              = #3;
type
  TIdTelnet = class;

  {Various states for telnet }
  TIdTelnetState =(tnsDATA, tnsIAC, tnsIAC_SB, tnsIAC_WILL, tnsIAC_DO, tnsIAC_WONT,
     tnsIAC_DONT, tnsIAC_SBIAC, tnsIAC_SBDATA, tnsSBDATA_IAC);

  {Commands to telnet client from server}
  TIdTelnetCommand = (tncNoLocalEcho, tncLocalEcho, tncEcho);

  TIdTelnetDataAvailEvent = procedure (Sender: TIdTelnet; const Buffer: String) of object;
  TIdTelnetCommandEvent = procedure(Sender: TIdTelnet; Status: TIdTelnetCommand) of object;

  {This object is for the thread that listens for the telnet server responses
  to key input and initial protocol negotiations }

  TIdTelnetReadThread = class(TIdThread)
  protected
    FClient: TIdTelnet;
    FRecvData: String;
    //
    procedure Run; override;
  public
    constructor Create(AClient: TIdTelnet); reintroduce;

    property  Client: TIdTelnet read FClient;
    property  RecvData: String read FRecvData write FRecvData;
  End; //TIdTelnetReadThread

  TIdTelnet = class(TIdTCPClient)
  protected
    fState: TIdTelnetState;
    fReply: Char;
    fSentDoDont: String;
    fSentWillWont: String;
    fReceivedDoDont: String;
    fReceivedWillWont: String;
    fTerminal : String;
    FOnDataAvailable: TIdTelnetDataAvailEvent;
    fIamTelnet: Boolean;
    FOnDisconnect: TNotifyEvent;
    FOnConnect: TNotifyEvent;
    FOnTelnetCommand: TIdTelnetCommandEvent;
    FTelnetThread: TIdTelnetReadThread;
    //
    procedure DoOnDataAvailable;
    procedure SetOnTelnetCommand(const Value: TIdTelnetCommandEvent);
    // what is our current state ?
    property State : TIdTelnetState read fState write fState;
    // what we send to the telnet server in response to protocol negotiations
    property Reply : Char read fReply write fReply;
    // did we send a DO DONT command?
    property SentDoDont : String read fSentDoDont write fSentDoDont;
    // did we send a WILL WONT command?
    property SentWillWont: String read fSentWillWont write fSentWillWont;
    // did we receive a DO DONT request from the server?
    property ReceivedDoDont: String read fReceivedDoDont write fReceivedDoDont;
    // did we receive a WILL WONT answer from the server?
    property ReceivedWillWont: String read fReceivedWillWont write fReceivedWillWont;
    // Are we connected to a telnet server or some other server?
    property IamTelnet: Boolean read fIamTelnet write fIamTelnet;
    // Protocol negotiation begins here
    function Negotiate(const Buf: String) : String;
    // Handle the termtype request
    procedure Handle_SB(CurrentSb: Byte; sbData: String; sbCount: Integer);
    // Send the protocol resp to the server based on what's in Reply    {Do not Localize}
    procedure SendNegotiationResp(var Resp: String);
    // Update the telnet status
    procedure DoTelnetCommand(Status: TIdTelnetCommand);
  public
    //
    constructor Create(AOwner: TComponent); override;
    procedure Connect(const ATimeout: Integer = IdTimeoutDefault); override;
    procedure Disconnect; override;
    procedure SendCh(Ch: Char);

    property TelnetThread: TIdTelnetReadThread read FTelnetThread;
  published
    property OnTelnetCommand: TIdTelnetCommandEvent read FOnTelnetCommand write SetOnTelnetCommand;
    property OnDataAvailable: TIdTelnetDataAvailEvent read FOnDataAvailable write FOnDataAvailable;
    property Terminal: string read fTerminal write fTerminal;
    property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
    property OnDisconnect: TNotifyEvent read FOnDisconnect write FOnDisconnect;
  end;

  EIdTelnetError = class(EIdException);
  EIdTelnetClientConnectError = class(EIdTelnetError);
  EIdTelnetServerOnDataAvailableIsNil = class(EIdTelnetError);

implementation

uses
  IdResourceStrings;

constructor TIdTelnetReadThread.Create(AClient: TIdTelnet);
begin
  inherited Create(False);
  FClient := AClient;
  FreeOnTerminate:= FALSE; //other way TRUE
end;

procedure TIdTelnetReadThread.Run;
begin
  // if we have data run it through the negotiation routine. If we aren't    {Do not Localize}
  // connected to a telnet server then the data just passes through the
  // negotiate routine unchanged.
  FRecvData := FClient.Negotiate(FClient.CurrentReadBuffer);
  // if textual data is returned by the server then send this data to
  // the client app
  Synchronize(FClient.DoOnDataAvailable);
  FClient.CheckForDisconnect;
end;

{ TIdTelnet }

procedure TIdTelnet.SendCh(Ch : Char);
begin
  // this  code is necessary to allow the client to receive data properly
  // from a non-telnet server
  if Ch <> CR then
    Write(Ch)
  else if (Ch = CR) and (IamTelnet = True) then
    Write(Ch)
  else
    Write(EOL);
end;

constructor TIdTelnet.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Port := 23;
  State := tnsData;
  SentDoDont := #0;
  SentWillWont := #0;
  ReceivedDoDont := #0;
  ReceivedWillWont := #0;
  Terminal := 'dumb';    {Do not Localize}
  IamTelnet := False;
end;

procedure TIdTelnet.Disconnect;
begin
  if Assigned(FTelnetThread) then begin
    FTelnetThread.Terminate;
  end;
  IAmTelnet := False;
  inherited Disconnect;
  if Assigned(FOnDisconnect) then begin
    OnDisconnect(SELF);

⌨️ 快捷键说明

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