witam mam otóż ciekawą <ort>wkestię </ort>do rozwiązania
zastanawiam się czy da się za pomocą programu client pobrać dane będące w tablicy w programie server, a także wysłać z client dane do tablicy na server? jeśli tak, to czy koś ma pomysła jak to zrobić? :]
Jaki w tym problem? Klient np wysyla jakies zadanie o ktorys tam element tablicy, serwer to odczytuje i wysyla ten element. Najlepiej, zeby przed jakim kolwiek transferem wysylany byl jakiegos rodzaju header informujacy o tym, co mamy zamiar wyslac i ile to ma zajmowac.
a czy ta metoda jest szybsza niż używanie plików? tj czy szybciej client pobierze dane z tablicy, czy szybciej pobierze dane z jakiegoś pliku na serwerze?
A ?<ort>z kad</ort>? w ogole przyszly ci pliki na mysl? Wiadomo, ze odczyt tablicy z ram jest szybsze niz pliku (choc, jesli jest to bardzo male i odczytane jeden raz to roznica bedzie marginalna). Z reszta nie do konca kapuje o co chodzi w tym rozwiazaniu z plikami :| .
otóż mamy na serwerze pliki powiedzmy z 1000 i w nich dane
każdy plik zawiera max 1kb
to samo mamy w 1000-elementowej tablicy danych w programie servera
(array[1..1000]of rekorddanych)
z serwerem lączy się jednocześnie 1000 osób
co szybciej będzie, gdyby te 1000 osób otworzyło odpowiedni dla siebie plik (w zależności od ID jakie posiadają) i pobrali dane i zapisali w tablicy programu client, czy też gdyby odwołali się do tablicy danych na serverze i dane z niego zapisali również w tablicy danych clienta?
ale ja motam :]
wolverine, a może jakiś przykłądzik prosty "zapodasz"? :]
Ogolnie tablica w pamieci bedzie zawsze szybsza, ale zwrocic tez nalezy uwage na to, ze jesli ten ID uzytkownika bedzie w jego rekordzie to bedzie trzeba przeszukac ta tablice, przy odczycie pliku zajmie sie tym system plikow i przypuszczam, ze zrobi to szybciej (choc moge sie mylic). W sumie, taka rzecz bardzo latwo sprawdzic, ustaw tablice na powiedzmy 10k elementow i tyle samo plikow, w tablicy element szukany na koncu i powrownaj. Co do przykladu, to nie wiem za bardzo co to ma byc za przyklad.
Wolverine, chciałbym abyś mi pomógł przekształcić ponizsze kody tak aby prócz samego transferu plików można było przesyłać wartości do tablicy, tj. z programu client z tablicacli przesyłamy jej wartości do tablicaserv na server i odwrotnie, poniżej wrzuciłem kody źródłowe
dzięki z góry za pomoc
<font color="red">client</span>
unit Client;
interface
uses
{$IFDEF Linux}
QGraphics, QControls, QForms, QDialogs, QStdCtrls,
{$ELSE}
windows, messages, graphics, controls, forms, dialogs, stdctrls,
{$ENDIF}
SysUtils, Classes, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient,
IdTrivialFTP;
type
<font color="green">tablicacli=array[1..100]of integer; //tu mają być dane</span>
TfrmMain = class(TForm)
edtRemoteFile: TEdit;
btnUpload: TButton;
edtHost: TEdit;
Label1: TLabel;
edtLocalFile: TEdit;
btnDownload: TButton;
TrivialFTP: TIdTrivialFTP;
Edit1: TEdit;
Label2: TLabel;
Label3: TLabel;
Edit2: TEdit;
procedure btnUploadClick(Sender: TObject);
procedure btnDownloadClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
plik:TextFile;
implementation
{$IFDEF MSWINDOWS}{$R *.dfm}{$ELSE}{$R *.xfm}{$ENDIF}
procedure TfrmMain.btnUploadClick(Sender: TObject);
var
s,log,has: string; vv:integer; v:string;
strm: TFileStream;
tf,zr:TextFile;
begin
log:=Edit1.Text;
has:=Edit2.Text;
assignfile(tf,Pchar(log)+'.txt');
rewrite(tf);
writeln(tf,log);
writeln(tf,has);
closefile(tf);
edtRemoteFile.Text:=Pchar(log)+'.txt';
edtLocalFile.Text:=Pchar(log)+'.txt';
s := edtRemoteFile.Text;
if s = '' then
s := ExtractFileName(edtLocalFile.Text);
with TrivialFTP do
begin
Host := edtHost.Text;
Put(edtLocalFile.Text, s);
end;
deletefile(Pchar(log)+'.txt');
end;
procedure TfrmMain.btnDownloadClick(Sender: TObject);
var
strm: TFileStream;
s: string;
begin
s := edtLocalFile.Text;
if s = '' then
s := ExtractFileName(edtRemoteFile.Text);
strm := TFileStream.Create(s, fmCreate);
with TrivialFTP do
try
Host := edtHost.Text;
Get(edtRemoteFile.Text, strm);
finally
strm.Free;
end;
end;
end.
<font color="red">server</span>
unit main;
interface
uses
{$IFDEF Linux}
QForms, QControls, QStdCtrls, QExtCtrls,
{$ELSE}
Forms, Controls, StdCtrls, ExtCtrls,
{$ENDIF}
IdTrivialFTPServer, Classes, transfer;
type
<font color="green">tablicaserv=array[1..100]of integer; //tu są dane do przesłania</span>
TfrmMain = class(TForm)
memLog: TMemo;
Panel1: TPanel;
edtRootDir: TEdit;
Label1: TLabel;
Label2: TLabel;
lblCount: TLabel;
btnBrowse: TButton;
procedure FormCreate(Sender: TObject);
procedure btnBrowseClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FTransferList: TList;
procedure TFTPReadFile(Sender: TObject; var FileName: string; const
PeerInfo: TPeerInfo;
var GrantAccess: Boolean; var AStream: TStream; var FreeStreamOnComplete:
Boolean);
procedure TFTPWriteFile(Sender: TObject; var FileName: string; const
PeerInfo: TPeerInfo;
var GrantAccess: Boolean; var AStream: TStream; var FreeStreamOnComplete:
Boolean);
procedure TFTPTransferComplete(Sender: TObject; const Success: Boolean;
const PeerInfo: TPeerInfo; AStream: TStream; const WriteOperation:
Boolean);
function CheckAccess(var FileName: string; RootDir: string): Boolean;
procedure AddTransfer(const FileName: string; const FileMode: Word; AStream:
TProgressStream);
public
end;
var
frmMain: TfrmMain;
implementation
{$IFDEF MSWINDOWS}{$R *.dfm}{$ELSE}{$R *.xfm}{$ENDIF}
uses FileCtrl, SysUtils;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
FTransferList := TList.Create;
edtRootDir.Text := GetCurrentDir;
with TIdTrivialFTPServer.Create(self) do
begin
OnReadFile := TFTPReadFile;
OnWriteFile := TFTPWriteFile;
OnTransferComplete := TFTPTransferComplete;
Active := True;
end;
end;
procedure TfrmMain.TFTPReadFile(Sender: TObject; var FileName: string;
const PeerInfo: TPeerInfo; var GrantAccess: Boolean; var AStream: TStream;
var FreeStreamOnComplete: Boolean);
var
s: string;
begin
FreeStreamOnComplete := False;
s := 'denied';
GrantAccess := CheckAccess(FileName, edtRootDir.Text);
try
if GrantAccess then
begin
AStream := TProgressStream.Create(FileName, fmOpenRead or
fmShareDenyWrite);
AddTransfer(FileName, fmOpenRead, TProgressStream(AStream));
s := 'granted';
lblCount.Caption := IntToStr(succ(StrToInt(lblCount.Caption)));
end;
finally
memLog.Lines.Add(Format('%s:%d - Read access to %s %s',
[PeerInfo.PeerIP, PeerInfo.PeerPort, FileName, s]));
end;
end;
procedure TfrmMain.TFTPTransferComplete(Sender: TObject;
const Success: Boolean; const PeerInfo: TPeerInfo; AStream: TStream; const
WriteOperation: Boolean);
var
s: string;
i: integer;
begin
try
if Success then
s := 'completed'
else
s := 'aborted';
memLog.Lines.Add(Format('%s:%d - Transfer %s - %d bytes transferred',
[PeerInfo.PeerIp, PeerInfo.PeerPort, s, AStream.Position]));
finally
for i := FTransferList.Count - 1 downto 0 do
if TfrmTransfer(FTransferList[i]).Stream = AStream then
begin
TfrmTransfer(FTransferList[i]).Free;
FTransferList.Delete(i);
end;
AStream.Free;
lblCount.Caption := IntToStr(pred(StrToInt(lblCount.Caption)));
end;
end;
procedure TfrmMain.TFTPWriteFile(Sender: TObject; var FileName: string;
const PeerInfo: TPeerInfo; var GrantAccess: Boolean; var AStream: TStream;
var FreeStreamOnComplete: Boolean);
var
s: string;
begin
FreeStreamOnComplete := False;
GrantAccess := CheckAccess(FileName, edtRootDir.Text);
s := 'denied';
try
if GrantAccess then
begin
AStream := TProgressStream.Create(FileName, fmCreate);
AddTransfer(FileName, fmCreate, TProgressStream(AStream));
s := 'granted';
lblCount.Caption := IntToStr(StrToInt(lblCount.Caption) + 1);
end;
finally
memLog.Lines.Add(Format('%s:%d - Write access to %s %s',
[PeerInfo.PeerIP, PeerInfo.PeerPort, FileName, s]));
end;
end;
procedure TfrmMain.btnBrowseClick(Sender: TObject);
var
s: string;
begin
s := edtRootDir.Text;
if SelectDirectory(s, [sdAllowCreate, sdPerformCreate, sdPrompt], 0) then
edtRootDir.Text := s;
end;
function TfrmMain.CheckAccess(var FileName: string; RootDir: string): Boolean;
var
s: string;
begin
RootDir := ExtractFileDir(ExpandFileName(IncludeTrailingBackslash(RootDir) +
'a.b'));
FileName := ExpandFileName(IncludeTrailingBackslash(RootDir) + FileName);
s := FileName;
SetLength(s, Length(RootDir));
Result := AnsiCompareText(RootDir, s) = 0;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
FTransferList.Free;
end;
procedure TfrmMain.AddTransfer(const FileName: string;
const FileMode: Word; AStream: TProgressStream);
begin
with TfrmTransfer(FTransferList[FTransferList.Add(TfrmTransfer.Create(self,
AStream, FileName, FileMode))]) do
begin
Parent := Self;
Show;
end;
end;
end.
Przykladowy program wysylajacy tablice:
Serwer
type
TPacket = record
Ind: Byte;
Element: Integer; //Typ, ktory masz w tablicy
end;
var
ServerArray: array[0..100] of Integer;
q: Integer;
Packet: TPacket;
begin
for q := Low(ServerArray) to High(ServerArray) do begin
Packet.Ind := q;
Packet.Element := ServerArray[q];
ServerSocket1.Socket.Connections[0].SendBuf(Packet, SizeOf(Packet));
end;
ServerSocket1.Socket.Connections[0].Close;
end;
Klient
type
TPacket = record
Ind: Byte;
Element: Integer; //Typ, ktory masz w tablicy
end;
var
ServerArray: array[0..100] of Integer;
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
Packet: TPacket;
begin
Socket.ReceiveBuf(Packet, SIzeOf(Packet));
ClientArray[Packet.Ind] := Packet.Element;
end;
Oczywiscie mozesz to przerobic tak, zeby klient wysylal informacje o tym, ktory element ma wyslac... ogolnie sie dziwie bo sa to rzeczy elementarne, no chyba, ze o cos innego chodzilo. Co do tamtego programu to nie mam indy (bo chyba na tym jest pisany) i bez sprawdzenia nic tam nie przerobie, z reszta tam jest jakis TIdTrivialFTP, a tutaj normalne skarpety
wolverine a z jakiego kożystasz komponentu?
Ze standardowych socketow dolaczonych do D6PE.
"osz kucze no" :]
no to ja coś pokombinuje z Indy bo nie mam tych co Ty miszczu ;)
mimo wszystko dzięki
pozdro