client/server dosya transferi ama sorun farklı

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
unicorn64
Üye
Mesajlar: 919
Kayıt: 04 Nis 2006 08:56
Konum: yine yeniden Ankara ^_^

client/server dosya transferi ama sorun farklı

Mesaj gönderen unicorn64 »

merhaba arkadaşlar. bi internet kafe programı yazmaya çalışıyorum. server dan farklı işlem istekleri gelebileceği için client e farklı değerler gönderyorum ve client de gelen isteğe göre işlem yapıo. bu istek türlerini if le kontrol etmeye çalıştığımda sorun çıktı sadece ilk if de doğru çalışıo diğerlerinde inaccessible expression diodu. ben de enumareted type tanımlaması yaptım ve onları gönderiyorum böylelikle case yapısını kullanma şansım oldu.
kodları da şöyle

server.pas

Kod: Tümünü seç

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList, ComCtrls, Menus, ScktComp,IniFiles, StdCtrls;
type
drm=(acik=0,acikOK=1,sureli=2,sureliOK=3,
       hspkapat=4,hspkapatOK=5,ekrangoruntu=6,ekrangoruntuOK=7);
type
  TForm1 = class(TForm)
    ListView1: TListView;
    ImageList1: TImageList;
    PopupMenu1: TPopupMenu;
    AkHesap1: TMenuItem;
    SreliHesap1: TMenuItem;
    HesapKapat1: TMenuItem;
    Server1: TServerSocket;
    N1: TMenuItem;
    BilgisayarYenidenBalat1: TMenuItem;
    BilgisayarKapat1: TMenuItem;
    N2: TMenuItem;
    HesapBilgisiAl1: TMenuItem;
    Memo1: TMemo;
    Button1: TButton;
    Memo2: TMemo;
    EkranGrntsAl1: TMenuItem;
    procedure AkHesap1Click(Sender: TObject);
   
    procedure ListView1ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure Server1ClientConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Server1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Button1Click(Sender: TObject);
    procedure Server1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
    function hangiclient(sckt:TCustomWinSocket):integer;
    procedure SreliHesap1Click(Sender: TObject);
    procedure islemyap(Sckt: TCustomWinSocket);
    procedure HesapKapat1Click(Sender: TObject);
    procedure EkranGrntsAl1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  str:string;
  Ini: TIniFile;
  baglanti:array of integer;
  bagli:integer;
  clientler:TStringList;
  durum:drm;
implementation

   uses unit2;
{$R *.dfm}


procedure TForm1.AkHesap1Click(Sender: TObject);
var cvp:integer;
begin
cvp:=MessageDlg( ListView1.Selected.Caption+' için açık hesap açmak istiyor musunuz ?',
   mtConfirmation,mbOKCancel,0);
   if cvp=mrOK then
   begin
    durum:=acik;
    server1.Socket.Connections[baglanti[ ListView1.Selected.Index]].SendBuf(durum,sizeof(durum));
   end;
end;


procedure TForm1.ListView1ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
begin
     if   ListView1.SelCount>0 then
      ListView1.PopupMenu:=PopupMenu1
     else
           ListView1.PopupMenu:=nil;
end;

procedure TForm1.FormCreate(Sender: TObject);
var adet,i:integer;
cl:string;
begin
ini:=TIniFile.Create(ChangeFileExt(Application.ExeName,'.INI'));
adet:=ini.ReadInteger('GENEL','PCADET',0);
setlength(baglanti,adet);
clientler:=TStringList.Create;
for i:=0 to adet-1 do
begin
cl:=ini.ReadString('PCADLARI','MASA'+inttostr(i+1),'');
ListView1.Items.Item[i].Caption:=cl;
clientler.Add(cl);
end;
Server1.Active:=true;
Server1.Open;
bagli:=0;
end;

procedure TForm1.Server1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var indx:integer;

begin
indx:=hangiclient(Socket);
//ListView1.Items.Item[j-1].Caption:='Masa '+inttostr(j)+
 // #13#10+'('+Socket.RemoteHost+')';
 ListView1.Items.Item[indx].ImageIndex:=1;
 baglanti[indx]:=bagli;
 bagli:=bagli+1;
 ShowMessage(Socket.RemoteHost+' bağlandı');
end;

procedure TForm1.Server1ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
ListView1.Items.Item[hangiclient(Socket)].ImageIndex:=0;
ShowMessage(Socket.RemoteHost+' ile bağlantı koptu');
bagli:=bagli-1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Server1.Socket.Connections[0].SendText(Memo1.Text);
//Server1.Socket.SendText('ok');
end;

procedure TForm1.Server1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
islemyap(Socket);
end;

function TForm1.hangiclient(sckt: TCustomWinSocket): integer;
begin
  Result:=clientler.IndexOf(sckt.RemoteHost);
end;

procedure TForm1.SreliHesap1Click(Sender: TObject);
var cvp:integer;
begin
cvp:=MessageDlg( ListView1.Selected.Caption+' için süreli hesap açmak istiyor musunuz ?',
   mtConfirmation,mbOKCancel,0);
   if cvp=mrOK then
   begin
   durum:=sureli;
   server1.Socket.Connections[baglanti[ ListView1.Selected.Index]].SendBuf(durum,sizeof(durum));
   end;
end;

procedure TForm1.islemyap(Sckt: TCustomWinSocket);
var bmp:TBitmap;
begin
     sckt.ReceiveBuf(durum,sizeof(durum));

     case durum of
     acikOK:ListView1.Items.Item[hangiclient(Sckt)].ImageIndex:=2;
     sureliOK:ListView1.Items.Item[hangiclient(Sckt)].ImageIndex:=3;
     hspkapatOK:ListView1.Items.Item[hangiclient(Sckt)].ImageIndex:=1;
     ekrangoruntuOK: begin
                       bmp:=TBitmap.Create;
                       Sckt.ReceiveBuf(bmp,sizeof(bmp));
                       bmp.SaveToFile(sckt.RemoteHost+'.bmp');
                       Form2.resimyukle(sckt.RemoteHost+'.bmp');
                       Form2.ShowModal;
                     end;
     else
     memo2.Lines.Add(sckt.ReceiveText);
     end;
end;

procedure TForm1.HesapKapat1Click(Sender: TObject);
var cvp:integer;
begin
cvp:=MessageDlg( ListView1.Selected.Caption+' hesabını kapatmak istiyor musunuz ?',
   mtConfirmation,mbOKCancel,0);
   if cvp=mrOK then
   begin
    durum:=hspkapat;
    server1.Socket.Connections[baglanti[ ListView1.Selected.Index]].SendBuf(durum,sizeof(durum));
   end;
end;

procedure TForm1.EkranGrntsAl1Click(Sender: TObject);
var cvp:integer;
begin
cvp:=MessageDlg( ListView1.Selected.Caption+' ekran görüntüsünü almak  istiyor musunuz ?',
   mtConfirmation,mbOKCancel,0);
   if cvp=mrOK then
   begin
    durum:=ekrangoruntu;
    server1.Socket.Connections[baglanti[ ListView1.Selected.Index]].SendBuf(durum,sizeof(durum));
   end;
end;

end.

client.pas

Kod: Tümünü seç

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp, StdCtrls;
type
drm=(acik=0,acikOK=1,sureli=2,sureliOK=3,
     hspkapat=4,hspkapatOK=5,ekrangoruntu=6,ekrangoruntuOK=7);
type
  TForm1 = class(TForm)
    Client1: TClientSocket;
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Client1Connect(Sender: TObject; Socket: TCustomWinSocket);
    procedure Button2Click(Sender: TObject);
    procedure Client1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure Client1Read(Sender: TObject; Socket: TCustomWinSocket);
    procedure Button3Click(Sender: TObject);
    procedure islemyap(Sckt: TCustomWinSocket);
    function getscreenshot():TBitmap;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  durum:drm;
  ekran:TBitmap;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Client1.Host:='hakan';
 Client1.Active:=true;
end;

procedure TForm1.Client1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
showmessage('client bağlanıyor');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Client1.Active:=false;
end;

procedure TForm1.Client1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
showmessage('client kopuyor');
end;

procedure TForm1.Client1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
//memo2.Lines.Add( socket.ReceiveText+' komutu alındı');

islemyap(Socket);
//ShowMessage(socket.ReceiveText);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Client1.Socket.SendText(memo1.Text);
end;

procedure TForm1.islemyap(Sckt: TCustomWinSocket);
begin
   Sckt.ReceiveBuf(durum,sizeof(durum));
   case durum of
   acik:  begin
          memo2.Lines.Add('açık hesap açıldı');
          durum:=acikOK;
          Client1.Socket.SendBuf(durum,sizeof(durum));
          end;
   sureli: begin
          memo2.Lines.Add('süreli hesap açıldı');
          durum:=sureliOK ;
          Client1.Socket.SendBuf(durum,sizeof(durum));
          end;
   hspkapat: begin
            memo2.Lines.Add('hesap kapatıldı');
            durum:=hspkapatOK;
            Client1.Socket.SendBuf(durum,sizeof(durum));
            end;
   ekrangoruntu:begin
                ekran:= getscreenshot;
                durum:=ekrangoruntuOK;
                Client1.Socket.SendBuf(durum,sizeof(durum));
                Client1.Socket.SendBuf(ekran,sizeof(ekran));

                end;

   else
     memo2.Lines.Add(sckt.ReceiveText);
   end;
end;

function TForm1.getscreenshot: TBitmap;
var
  Desktop:HDC;
begin
  Result:= TBitmap.Create;
  Desktop:= GetDC(0);
  try
  try
    Result.PixelFormat:=pf32bit;
    Result.Width:=Screen.Width;
    Result.Height:=Screen.Height;
    BitBlt(Result.Canvas.Handle,0,0,Result.Width,Result.Height,Desktop,0,0,SRCCOPY);
    Result.Modified:=True;
  finally
    ReleaseDC(0,Desktop);
  end;
  except
    Result.Free;
    Result:=nil;
  end;
end;

end.


client server yapısıyla yeni tanıştığım için şimdilik sadece iletişimi görme açısından yazı yazdırmakla yetiniyorum.

şimdi bu yapıya göre clientin ekran resmini almaya çalışıyorum. ama dosyayı nasıl göndereceğimi bilemedim. forumda bi kaç mesaj buldum ama benim yapıya uyduramadım bi türlü.


sizce ne yapmalıyım
mkysoft
Kıdemli Üye
Mesajlar: 3110
Kayıt: 26 Ağu 2003 12:35
Konum: Berlin
İletişim:

Mesaj gönderen mkysoft »

Bence bu şekilde bir yapıda dosya transferi yapmanız çok zor olur. Bunun yerine şu şekilde bir yapı kullanın. Client/Server kendi arasında text modu ile haberleşsin. Öncelikle bir kod bloğu belirleyin. Mesala mesajın ilk 3 karakteri komut olsun. Bu komutlardan biride dosya transferi olabilir. çektiğiniz ekran resmini binary modda okuyup text olarak server'a gönderin (doysanın tamamı tek seferde server'a gitmeyebilir bu nedenle parçalara bölmek gerekebilir). Buna benzer bir şey yapmıştım bende Visual Basic'te.
Kullanıcı avatarı
unicorn64
Üye
Mesajlar: 919
Kayıt: 04 Nis 2006 08:56
Konum: yine yeniden Ankara ^_^

Mesaj gönderen unicorn64 »

tamam dosya transferinden vazgeçtim :P peki bu yapı ve mantık diğer işlemler için uygun olur mu sizce.

karşılıklı kontrol ifadeleriyle senkron ve daha garantili bir çalışma olur diye düşünüyorum. çünkü çeşitli nedenlerle server-client arası iletişim istenen şekilde sağlanamamış olabilir, gönderilen bi istek alınamamış yada alındığı halde gerekli işlem uygulanamamış olabilir diye endişe edip karşılıklı komut göndermeler kullandım ama programlamayı ve çalışma mantığını biraz zorlayacak gibi görünüyor. sizce bu yöntem gerekli mi yoksa mesela server bi iş yap desin ve direk yapıldı kabul etsin demek uygun olur mu??

bu arada binary modda okuyup text modda gönderme işlemini nasıl yapabilirim. tam anlamadım. delphide binary işlem yapmadım daha önce. mesela biraz offtopic olcak ama bir sayıyı nasıl binary olarak ifade edebilirim??
ulu coder
Üye
Mesajlar: 838
Kayıt: 01 Nis 2006 06:46
Konum: Ankara

Mesaj gönderen ulu coder »

unicorn, 8 ay cafe programıyla uğraşıp henüz bitirmiş ve client-server arasındaki iletişim sonucu kafayı yemiş birisi olarak sanırım yardımcı olabilirim :shock:

Gelen text veriyi değerlendirken neden sadece ilk if'in
çalıştığını söyleyeyim.

Kod: Tümünü seç

If ReceiveText = 'hede' then...
If ReceiveText = 'hödö' then...
sanırım karşılaştırmayı bu şekilde yapıyorsunuz. Fakat şöyle bir durum var, ReceiveText'i bir kez kullandığınızda yeni veri gelene kadar içeriği nil oluyor. Yani bir kez daha okuyamıyorsunuz. Bu nedenle OnRead içinde karşılaştırma yapmadan önce 'Msg := ReceiveText' gibi gelen mesajı bir değişkene aktarın, ve sonra if'lerde bu değişkeni kullanın.

Sayıyı şu şekilde binary olarak ifade edebilirsiniz :ara inttobin

Dosya aktarımı için birer tane daha socket kullanmanız işinizi çoook kolaylaştırır.

Bir de ufak bir rica, tüm unit'i değil de görmemiz gereken kısmı yazarsanız memnun oluruz.

Kolay gelsin...
Kullanıcı avatarı
unicorn64
Üye
Mesajlar: 919
Kayıt: 04 Nis 2006 08:56
Konum: yine yeniden Ankara ^_^

Mesaj gönderen unicorn64 »

öncelikle teşekkürler. en geç hazirana kadar bitirmem gerek ve özellikle client-server de baya acemiyim :oops: :cry: sanırım başınızı baya bi ağrıtıcam.
Sayıyı şu şekilde binary olarak ifade edebilirsiniz inttobin
haklısınız kesinlikle :ara sorry

farklı bi yontem kullandığım için yapıyı tam görmeniz gerekir diye düşünerek tüm uniti eklemiştim ama tabi genede aradan sadece gerekli kısımlar alınabilirdi, kafam baya dalgın ve cozutmuştum o sırada sanırım ondan oldu...

bi de mesela sipariş vs gibi değerler için de text bazlı mı çalışmam uygun olur. yada şöyle sorayım her istek farklı turden değerlerle çalışmamı gerektircek sanırım yani hangi durumda neyi kullanacağımı nasıl bilebilirim...?
ulu coder
Üye
Mesajlar: 838
Kayıt: 01 Nis 2006 06:46
Konum: Ankara

Mesaj gönderen ulu coder »

Bana sorarsanız en güzel yöntem şudur;parametrelerinizi mesaja gömmek ve bu değerleri mesajdan almak için iki prosedür oluşturun, her işinizi bu iki prosedürle yapın, yani sırf text alıp gönderin. Bu iki işlem için yazdığım prosedürler var, fakat ne yazık ki, programı şirket adına yazdığım için paylaşamıyorum.

Sınırları zorlayarak bir tavsiye daha: mesajları şu şekilde oluşturun:

işlem adı - parametreler

Her işlem için ayrı prosedür oluşturun. Mesajın ne olduğuna (yeni sipariş vs. vs.) 'işlem adı' kısmına bakarak karar verin, karar verdikten sonra tüm mesajı ilgili prosedüre parametre olarak geçin. Prosedür içinde mesajdan parametreleri alıp gerekli işlemleri yapın.

Kod olarak yardımcı olmak isterdim, ama maalesef :roll:
Cevapla