Algoritma Önerileri

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
akissoftware
Üye
Mesajlar: 118
Kayıt: 17 Ağu 2010 09:08

Algoritma Önerileri

Mesaj gönderen akissoftware »

Arkadaşlar merhaba;

Bir yazılım yapmaya çalışıyorum. Yazılım içinde normalde 1 adet tsock componenti kullanıp bir portu dinliyorum ve gelen mesajları listeliyorum. Buraya kadar bir problem yok.

Fakat kullanıcı birden fazla alıcı eklebilmeli. Her eklediği alıcı farklı portu dinleyecek. Bunu dizayn anında yapabilme imkanım varmı? Veya başka bir yolu varmıdır ?

Örnek olarak bir adet alıcı ekledim ve bu 10001 portunu dinliyor. Bir adet daha ekledim o da 10002 portunu dinliyor. Bu ayarları bir veritabanına kaydedip program açıldığı anda ayarlara göre ilgili portların dinlenmesini nasıl sağlayabilirim ? Sonuçta kullanıcının kaç adet alıcı ekleyeceğini bilmiyorum ve bununda 5-10 ile sınırlı olmayacağını düşünüyorum..

Herkese teşekkürler
Kullanıcı avatarı
fesiharslan
Üye
Mesajlar: 591
Kayıt: 20 Eki 2006 11:37
Konum: Erzurum
İletişim:

Re: Algoritma Önerileri

Mesaj gönderen fesiharslan »

Merhaba;
Üç adet tablo ile bu işlemleri gerçekleştirebilirsiniz.
Kullanıcı Tablosu: Uygulamayı kullanan son kullanıcı bilgilerini içerir.
Soket Tablosu: Aktif olan soket ve port bilgilerini içerir.
Kullanıcı_Soket Tablosu: Hangi kullanıcının hangi soketleri ve hangi portları dinlediğini içerir.

Yöntem olarak;
Aktif Tüm soketler için Ortak Receive metodu yazılır.
Uygulama başlatıldığı anda soket tablosu okunur.
Tablo sayısınca kayıtlar döngüye tabi tutulur.
Her döngüde dinamik bir Soket oluşturulur ve özellikleri Set edilir. (PortNo, OnReceive vb.)
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: Algoritma Önerileri

Mesaj gönderen ertank »

Merhaba,

Kullandığın Delphi versiyonunu belirtmemişsin. Benim aşağıda anlattıklarım Delphi 10 için geçerlidir. Yüksek ihtimalle birçok XE sürümünde de çalışacaktır.

Sadece tek bir nesne dinamik olarak çalışma zamanında kullanılacak ise şuradaki örneği inceleyebilirsin:
http://forums.devshed.com/delphi-progra ... 89039.html

Ancak birden fazla, farklı nesneler için TObjectList kullanabilirsin. İki farklı kullanımı var. Basit bir örnek için aşağıdaki kodu inceleyebilirsin. İnternette daha detaylı aramalar yapmanı tavsiye ederim.


Program çalıştığında dinamik olarak nesneleri oluşturmak için aşağıdaki gibi bir yöntem izleyebilirsin.

Kod: Tümünü seç

uses System.Contnrs, // TObjectList
    Vcl.ExtCtrls, // TTimer
    IdFTP; // TIdFTP

// Farklı nesneler dinamik olarak oluşturulacağı için sınıf tanımı kullanılıyor.
type
  TMyClass = class(TObject)
    newTmr                    : TTimer;
    newidFTP                  : TidFTP;
    Active                    : Boolean;
  end;
  
type
  TfrmMain = class(TForm)
    TrayIcon1: TTrayIcon;
    ApplicationEvents1: TApplicationEvents;
    Timer1: TTimer;
    .
    .
    .
  private
    { Private declarations }
    var
      fList:TObjectList; // Dinamik oluşturulacak nesneleri içinde saklayacağımız TObjectList değişkeni
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
var
  cls:TMyClass;  
begin
  // Dinamik oluşturulan nesnelerin listesinin saklanacağı Obje Listesini oluştur
  fList := TObjectList.Create(False);
  // Yukarıdaki parametre anlamı:
  // True = TObjectList.Free çalıştırıldığında içindeki nesneleri kendisi Free etsin.
  // False = biz kendimiz Free edeceğiz.
  // Daha önce True kullandığımda kendisi free edemediği için ben kod yazarak hafıza kontrolü yapmayı tercih ediyorum.
  
  // FOR ... aşağıdaki kısımı bir döngü içine koyulduğu zaman istediğin kadar dinamik olarak nesne oluşturabilirsin.
      cls := TMyClass.Create;
      // CLASS içindeki değişkenlere direk atamalar yapabiliriz.
      cls.Active := True;
      // CLASS içindeki nesneler kullanılmadan önce create edilmeli
      cls.newTmr := TTimer.Create(nil);
      cls.newTmr.Interval := 0; // Normalde sıfır olarak ayarla
      cls.newTmr.Interval := 5 * 60000;  // 5 dakikada bir çalış
      cls.newTmr.OnTimer  := Timer1Timer;  // Tüm Timer nesneleri aynı prosedürü paylaşsın. Yapacakları iş aynı
      cls.newTmr.Enabled  := False;  // Hemen çalışmaya başlama
      cls.newTmr.Tag      := 20;  // aradığın nesneyi bulmak adına nesnenin bir parametresine indeks bilgisini kaydetmek gerekecektir. FOR döngüsü kullanırsan döngü değişkenini burada kullanabilirsin.
      // CLASS içindeki nesneler kullanılmadan önce create edilmeli
      cls.newidFTP := TidFTP.Create(nil); 
      cls.newidFTP.Host                  := '192.168.1.5';
      cls.newidFTP.Username                := 'test@test.com';
      cls.newidFTP.Password                := 'anonymous';
      cls.newidFTP.Passive                 := True;
  
      // Gerekli tüm parametreler tanımlandıktan sonra nesneleri TObjectList içinde saklansın
      fList.Add(cls);
    // END FOR
end;
Nesneler oluşturulduktan sonra zamanı geldiğinde aşağıdaki gibi bir yöntem ile ilgili nesneyi TObjectList içinden bulup kullanabilirsin.

Kod: Tümünü seç

function TfrmMain.FindMyClass(idx:Integer; var cls:TMyClass): Boolean;
var i:Integer;
begin
  Result := False;
  for i := 0 to fList.Count-1 do begin
    if TMyClass(fList[i]).newTmr.Tag = idx then begin
      cls := TMyClass(fList[i]);
      Result := True;
      Break;  // aradığımızı bulduk. artık çıkabiliriz.
    end;
  end;
end;



procedure TfrmMain.Timer1Timer(Sender: TObject);
var
  cls:TMyClass;
begin
  // TAG içine hangi Timer nesnesini kullanacağımıza dair bilgiyi OnFormCreate zamanında saklamış olmamız gerekli
  // Bu noktada hangi Timer çalıştığını Timer.Tag parametresinden ayırt edebiliriz.
  if not FindMyClass((Sender as TTimer).Tag, cls) then Exit;
  // Artık cls içinde kullanacağımız bilgiler var. Ne istiyorsak yapabiliriz.
  cls.newidFTP.Connect;
  cls.newidFTP.Disconnect;
end;
Önemli bir nokta da kapanırken hafızada kalıntı bırakmamaktır. Bunu OnDestroy olayında kontrol altına alabiliriz.

Kod: Tümünü seç

procedure TfrmMain.ClearMemory;
var
  i:Integer;
  cls:TMyClass;
begin
  for i := 0 to fList.Count-1 do begin
    cls := (fList[i] as TMyClass);
    cls.newTmr.Free;
    cls.newidFTP.Free;
    fList[i].Free;
  end;
  fList.Free;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  ClearMemory;
end;

Alışkanlık olarak her programın geliştirme safhasında hafızada kaçak olmadığını anlamak adına proje dosyanın içine (Project->View Source) aşağıdaki satırı eklemeni tavsiye ederim.

Kod: Tümünü seç

ReportMemoryLeaksOnShutdown := True;
Böylece uygulama kapatıldığında eğer bir hafıza kaçağı varsa sana bir mesaj içinde ne tür nesneleri hafızadan temizleyemediğini bildirecektir.
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: Algoritma Önerileri

Mesaj gönderen Lord_Ares »

Bütün İletişimi tek bir port dinleyerek sağlaman daha doğru olur çünkü her açtığın port için, işletim sisteminin güvenlik duvarında belli izinler isteyecek ve bunları düzenlemen zorlaşacaktır. ( Örneğin açamaya çalıştığın portlardan birini yeni kurduğun bir program kullanıyor olması vs gibi sorunlar..)
Bunun yerine tek bir port kullan, her bağlanan kullanıcının mesajı içinde benzersiz kimlik tanımlayıcı ( id no ) numara ile mesaj göndersin. Veritabanını karşılaştırır bu id ye sahip biri yoksa yeni kullanıcımı , kayıtlı kullanıcımı olduğunu anlamış olursun.
Cevapla