Глубины Indy. 2. Техническая поддержка
Скачать 1.03 Mb.
|
20.1.6.1.2. Не явное разрушение .Net разделяет эти функции – финализации и освобождения памяти, поскольку памятью заведует .NET. .Net использует неявное разрушение. Если вы работали с интерфейсами, то семантика подсчета ссылок, используемая в интерфейсах аналогична. Вместо явного разрушения, когда объект сам разрушается, CLR подсчитывает ссылки на объект. Когда объект больше не используется, то он помечается для разрушения. 20.1.6.2. Сборка мусора (Garbage Collection) .Net использует сборку мусора, что бы очистить память используемую объектом. Это название процесса, который определят, что объект больше используется и освобождает занятую им память. Сборка мусора .NET очень сложная и даже базовая информация заслуживает отдельной главы, если даже не статьи. 114 Подобно явному и неявному разрушению, сборка мусора имеет малое влияние на перенос приложения. Поскольку для процедуры переноса, сборка мусора является ящиком фокусника, который заботится о разрушении объекта за вас. 20.1.7. Шаги по переносу Перенос приложений в Delphi .NET для большинства приложений будет очень значимым и потребует определенной осторожности. Для большинства объектно-ориентированного кода, проще чем кажется. Данная статья не может уменьшить количество работы по переносу, но поможет вам сделать это легче. Она позволит уменьшить количество ошибок и предназначена для быстрой реализации переноса. 20.1.7.1. Удаление предупреждений (Unsafe Warnings) To remove unsafe warnings, load the target project into Delphi 7. With the unsafe warnings turned on, perform a build all. Delphi will produce a series of unsafe warnings. Each warning needs to be eliminated. This may easily be the biggest step in porting your application. 20.1.7.2. Модули и пространство имен Директивы Uses должны быть преобразованы к использованию пространства имен. Если код требует одновременного использования в Windows и в .NET framework данные модули должны использовать IFDEF как указано. Константа CLR определена в Delphi .NET. uses {$IFDEF CLR} Borland.Win32.Windows {$ELSE} Windows {$ENDIF} , {$IFDEF CLR} Borland.Delphi.SysUtils {$ELSE} SysUtils {$ENDIF} , {$IFDEF CLR} Borland.Vcl.Forms {$ELSE} Forms {$ENDIF} ; Пространство имен будет увидено. Три главных из них – это Borland.Win32 (Windows), Borland.Delphi (RTL) and Borland.VCL (VCL for .NET). 20.1.7.3. Преобразование DFM Delphi for .NET пока не поддерживает формат DFM. Это возможно будет в будущем, так что данный шаг требуется если вы желаете использовать бета версию DCCIL. Поскольку DFM не поддержаны, все формы должны быть сконструированы с помощью кода. Есть также программа разработанная для выполнения данной задачи, которая может быть использована с нормальным приложениями Delphi. 20.1.7.4. Преобразование файла проекта Application.CreateForm более не поддержан, так что формы должны быть созданы вручную, как обычные компоненты. Для установки главной формы приложения, установите свойство Application.MainForm перед вызовом Application.Run. 20.1.7.5. Разрешение с различиями в классах 115 Во время компиляции могут проявиться различия между VCL for .NET и VCL, поскольку появились небольшие различия между VCL и Visual CLX. Каждое из этих различий должно быть разрешено с помощью IFDEF. 20.1.7.6. Нужна удача Если вам повезло, то ваш проект преобразован и работает нормально. Перенос – это не только перекомпиляция и потребует некоторого времени. Перенос в .NET требует подобных усилий, которые нужны для переноса в из VCL приложений в Visual CLX. Хотя время и усилия значительны, но это все равно меньше, чем писать с нуля и позволяет делать кросс платформенную разработку, так как код будет повторно использоваться и там и там, конечно если он спланирован должным образом. 20.1.8. Благодарности Я использовал много источников. Я извиняюсь, если я кого-то забыл указать в благодарностях. Я желаю поблагодарить следующих товарищей: John Kaster, Brian Long, Bob Swart, Lino Tadros, Danny Thorpe, Eddie Churchill, Doychin Bondzhev. 21. Об авторах 21.1. Chad Z. Hower a.k.a Kudzu Чад Хувер (Chad Z. Hower), известный так же, как "Kudzu" является автором и координатором проекта Internet Direct (Indy). Indy состоит из более, чем 110 компонент и является частью Delphi, Kylix и C++ Builder. В опыт Чада входит работа с трудоустройством, безопасность, химия, энергетика, торговля, телекоммуникации, беспроводная связь и страховая индустрии. Особая область Чада это сети TCP/IP, программирование, межпроцессорные коммуникации, распределенные вычисления, Интернет протоколы и объектно-ориентированное программирование. Когда он не занимается программирование, то он любит велосипед, каяк, пешие прогулки, лыжи, водить и просто чем ни будь заниматься вне дома. Чад, чей лозунг "Программирование это искусство, а не ремесло", также часто публикует статьи, программы, утилиты и другие вещи на Kudzu World http://www.Hower.org/Kudzu/. Чад как истинный американский путешественник, проводит свое лето в Санкт- Петербурге, Россия, а зиму в Лимасоле на Кипре. Чад доступен через Веб форму. Чад является ведущим разработчиком в Atozed Software. 21.2. Hadi Hariri Hadi Hariri – это старший разработчик и ведущий проекта в Atozed Computer Software Ltd. (http://www.atozedsoftware.com/) и также помощник координатора проекта Internet Direct (Indy), Open-source проект TCP/IP компонент, который включен в Kylix и Delphi 6. раньше работал для ISP и в программисткой компании, он имеет твердые знания Internet и клиент- серверных приложений, как сетевой администратор и администратор по безопасности. 116 Hadi женат и проживает в Испании, где он главный авто для журнала по Delphi и участник Borland Conferences и пользовательских групп. Создано: 19.04.2009 Исходный код IdSMTP.pas Исходный код компонента даёт понимание его алгоритма работы с принимающим почтовым сервером. unit IdSMTP; interface uses Classes, IdGlobal, IdMessage, IdEMailAddress, IdHeaderList, IdMessageClient; type TAuthenticationType = (atNone, atLogin); const ID_TIDSMTP_AUTH_TYPE = atNone; type TIdSMTP = class (TIdMessageClient) protected FDidAuthenticate: Boolean; FAuthenticationType: TAuthenticationType; FAuthSchemesSupported: TStringList; FMailAgent: string ; FPassword: string ; FUserId: string ; procedure GetAuthTypes; function IsAuthProtocolAvailable(Auth: TAuthenticationType) : Boolean; virtual ; public procedure Assign(Source: TPersistent); override ; function Authenticate: Boolean; virtual ; procedure Connect; override ; constructor Create(AOwner: TComponent); override ; destructor Destroy; override ; procedure Disconnect; override ; class procedure QuickSend(const AHost, ASubject, ATo, AFrom, AText: string ); procedure Send(AMsg: TIdMessage); virtual ; property AuthSchemesSupported: TStringList read FAuthSchemesSupported; published property AuthenticationType: TAuthenticationType read FAuthenticationType write FAuthenticationType default ID_TIDSMTP_AUTH_TYPE; property MailAgent: string read FMailAgent write FMailAgent; 117 property Password: string read FPassword write FPassword; property UserId: string read FUserId write FUserId; property Port default IdPORT_SMTP; end ; implementation uses IdCoder3To4, IdResourceStrings, SysUtils; procedure TIdSMTP.Assign(Source: TPersistent); begin if Source is TIdSMTP then begin AuthenticationType := TIdSMTP(Source).AuthenticationType; Host := TIdSMTP(Source).Host; MailAgent := TIdSMTP(Source).MailAgent; Password := TIdSMTP(Source).Password; Port := TIdSMTP(Source).Port; UserId := TIdSMTP(Source).UserId; end else inherited ; end ; function TIdSMTP.Authenticate: Boolean; function AuthLogin: Boolean; begin SendCmd( 'auth LOGIN' , 3 34); SendCmd(Base64Encode(UserId), 3 34); SendCmd(Base64Encode(Password), 2 35); Result := True; end ; begin Result := False; case FAUthenticationType of atLogin: Result := AuthLogin; end ; FDidAuthenticate := True; end ; procedure TIdSMTP.Connect; begin inherited ; try GetResponse([ 2 20]); FAuthSchemesSupported.Clear; if SendCmd( 'ehlo ' + LocalName) = 2 50 then begin GetAuthTypes; end else begin SendCmd( 'Helo ' + LocalName, 2 50); end ; except Disconnect; raise ; end ; 118 end ; constructor TIdSMTP.Create(AOwner: TComponent); begin inherited ; FAuthSchemesSupported := TStringList.Create; FAuthSchemesSupported.Duplicates := dupIgnore; Port := IdPORT_SMTP; end ; destructor TIdSMTP.Destroy; begin FreeAndNil(FAuthSchemesSupported); inherited ; end ; procedure TIdSMTP.Disconnect; begin try if Connected then begin WriteLn( 'Quit' ); end ; finally inherited ; FDidAuthenticate := False; end ; end ; procedure TIdSMTP.GetAuthTypes; var Iterator: Integer; Buffer: string ; ListEntry: string ; begin Iterator := 1 ; while Iterator < FCmdResultDetails.Count do begin Buffer := UpperCase(FCmdResultDetails[Iterator]); if (IndyPos( 'AUTH' , Buffer) = 5 ) and ((Copy(Buffer, 9 , 1 ) = ' ' ) or (Copy(Buffer, 9 , 1 ) = '=' )) then begin Buffer := Copy(Buffer, 1 0, Length(Buffer)); while Buffer <> '' do begin StringReplace(Buffer, '=' , ' ' , [rfReplaceAll]); ListEntry := Fetch(Buffer, ' ' ); if (FAuthSchemesSupported.IndexOf(ListEntry) = - 1 ) then FAuthSchemesSupported.Add(ListEntry); end ; end ; Inc(Iterator); end ; end ; function TIdSMTP.IsAuthProtocolAvailable( Auth: TAuthenticationType): Boolean; begin case Auth of atLogin: Result := (FAuthSchemesSupported.IndexOf( 'LOGIN' ) <> - 1 ); else Result := False; end ; 119 end ; class procedure TIdSMTP.QuickSend(const AHost, ASubject, ATo, AFrom, AText: string ); var SMTP: TIdSMTP; Msg: TIdMessage; begin SMTP := TIdSMTP.Create(nil); try Msg := TIdMessage.Create(SMTP); with Msg do begin Subject := ASubject; Recipients.EMailAddresses := ATo; From.Text := AFrom; Body.Text := AText; end ; with SMTP do begin Host := AHost; Connect; try ; Send(Msg); finally Disconnect; end ; end ; finally SMTP.Free; end ; end ; procedure TIdSMTP.Send(AMsg: TIdMessage); procedure WriteRecipient(const AEmailAddress: TIdEmailAddressItem); begin SendCmd( 'RCPT to:<' + AEMailAddress.Address + '>' , 2 50); end ; procedure WriteRecipients(AList: TIdEmailAddressList); var i: integer; begin for i := 0 to AList.count - 1 do begin WriteRecipient(AList[i]); end ; end ; function NeedToAuthenticate: Boolean; begin if FAuthenticationType <> atNone then begin Result := IsAuthProtocolAvailable(FAuthenticationType) and (FDidAuthenticate = False); end else begin Result := False; end ; end ; 120 begin SendCmd( 'Rset' ); if NeedToAuthenticate then begin Authenticate; end ; SendCmd( 'Mail from:<' + AMsg.From.Address + '>' , 2 50); WriteRecipients(AMsg.Recipients); WriteRecipients(AMsg.CCList); WriteRecipients(AMsg.BccList); SendCmd( 'Data' , 3 54); AMsg.ExtraHeaders.Values[ 'X-Mailer' ] := MailAgent; SendMsg(AMsg); SendCmd( '.' , 2 50); end ; end Пример с исходниками простейшего SMTP сервера Просетйший SMTP север из примеров работы с компонентами Indy { $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: 108528: Main.pas { { Rev 1.0 14/08/2004 12:29:18 ANeillans { Initial Checkin } { Demo Name: SMTP Server Created By: Andy Neillans On: 27/10/2002 Notes: Demonstration of SMTPServer (by use of comments only!!) Read the RFC to understand how to store and manage server data, and therefore be able to use this component effectivly. Version History: 14th Aug 04: Andy Neillans Updated for Indy 10, rewritten IdSMTPServer 12th Sept 03: Andy Neillans Cleanup. Added some basic syntax checking for example. Tested: Indy 10: D5: Untested D6: Untested D7: Untested } unit Main; 121 interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, IdBaseComponent, IdComponent, IdTCPServer, IdSMTPServer, StdCtrls, IdMessage, IdEMailAddress, IdCmdTCPServer, IdExplicitTLSClientServerBase; type TForm1 = class (TForm) Memo1: TMemo; Label1: TLabel; Label2: TLabel; Label3: TLabel; ToLabel: TLabel; FromLabel: TLabel; SubjectLabel: TLabel; IdSMTPServer1: TIdSMTPServer; btnServerOn: TButton; btnServerOff: TButton; procedure btnServerOnClick(Sender: TObject); procedure btnServerOffClick(Sender: TObject); procedure IdSMTPServer1MsgReceive(ASender: TIdSMTPServerContext; AMsg: TStream; var LAction: TIdDataReply); procedure IdSMTPServer1RcptTo(ASender: TIdSMTPServerContext; const AAddress: String ; var VAction: TIdRCPToReply; var VForward: String ); procedure IdSMTPServer1UserLogin(ASender: TIdSMTPServerContext; const AUsername, APassword: String ; var VAuthenticated: Boolean); procedure IdSMTPServer1MailFrom(ASender: TIdSMTPServerContext; const AAddress: String ; var VAction: TIdMailFromReply); procedure IdSMTPServer1Received(ASender: TIdSMTPServerContext; AReceived: String ); private { Private declarations } public { Public declarations } end ; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.btnServerOnClick(Sender: TObject); begin btnServerOn.Enabled := False; btnServerOff.Enabled := True; IdSMTPServer1.active := true; end ; procedure TForm1.btnServerOffClick(Sender: TObject); begin btnServerOn.Enabled := True; btnServerOff.Enabled := False; IdSMTPServer1.active := false; end ; procedure TForm1.IdSMTPServer1MsgReceive(ASender: TIdSMTPServerContext; AMsg: TStream; var LAction: TIdDataReply); var LMsg : TIdMessage; 122 LStream : TFileStream; begin // When a message is received by the server, this event fires. // The message data is made available in the AMsg : TStream. // In this example, we will save it to a temporary file, and the load it using // IdMessage and parse some header elements. LStream := TFileStream.Create(ExtractFilePath(Application.exename) + 'test.eml' , fmCreate); |