mam drobny problem... otoz robie sobie screen'a klikajac clienta na moim komputerze do servera na laptopie... wszystko ladnie sie robi, jpg zapisuje sie na dysku i tutaj nie wiem co zrobic... w jaki sposob wyslac/odeslac jpg do mojego komputera (klient) ??
na pewno jest w FAQu albo artach gtowe rozwiązanie
przejrzalem wszystko... ARTYKULY, FAQ, GOTOWCE i nic nie znalazlem na temat wysylania jpg przez ClientSocket i ServerSocket... :(
Dodaj w Kliencie Buttona i w OnClick dodaj coś takiego:
Client.WriteLn('GETIMG');
Client.ReadBuffer(Bufor, iledanychodczytac); //albo ReadStream(twoj strumien do pliku);
FreeAndNil(twoj strumien do pliku); //tylko w przypadku korzystania ze strumieni
i to by bylo na tyle..
a w Serverze w OnExecute dodaj
var
Command : String;
begin
Command := Server.ReadLn();
if Command = 'GETIMG' then
begin
AThread.Connection.OpenWriteBuffer;
AThread.WriteStream(strumiendopliku);
AThread.CloseWriteBuffer;
end;
</delphi>
ojjj nie za bardzo rozumie... u mnie to wyglada inaczej...
Client.WriteLn('blabla');
rowna sie u mnie:
ClientSocket1.Socket.SendText('blabla');
i jeszcze inne rzeczy
wiadomosc:string
if (wiadomosc='blabla')
then
begin
...
end;
a dalszej/innej wersji nie rozumie... moze ktos to wytlumaczyc jak powinno wygladac ? aby przeslalo obraz ? moze jakies strony ? artykuly ? faq ? cokolwiek ? :)
Z jakich komponentów korzystasz? Jeżeli z podstawowych (TClientSocket i TServerSocket) z D6, to raczej marnie to widzę...
Z bibliotekami Indy mi to lepiej szło... gdyż umieszczałem jeszcze komponent IdTrivialFTP. Klient wysyła żądanie (np. 'Te, idiota. Polacz sie ze mna na porcie tftp i pobierz plik'), a serwer grzecznie się podłącza i plik pobiera.
Jeżeli znacie lepsze sposoby, z chęcią wysłucham :D
[edit]
Przykładowy kodzik z mojej aplikacji zdalnego sterowania komputerem (xd)
if cmd = 'takescreenshot' then
begin
c := TCanvas.Create;
c.Handle := GetWindowDC(GetDesktopWindow);
b := TBitmap.Create;
b.Width := screen.Width;
b.Height := screen.Height;
b.Canvas.CopyRect(Rect(0,0,screen.Width,screen.Height),c,Rect(0,0,screen.Width,screen.Height));
jpg := TJpegImage.Create;
jpg.CompressionQuality := 80;
jpg.Assign(b);
jpg.Compress;
jpg.SaveToFile('c:\clipboard.jpeg');
SendCmdP('screenshotavailable',socket,'c:\clipboard.jpeg'); // Poinformuj klienta o tym, ze plik jest juz gotowy.
end;
A tutaj kodzik klienta:
if cmd = 'screenshotavailable' then
begin
IdFTP.Get(lparam,'tmp.jpg');
imgScreen.Picture.LoadFromFile('tmp.jpg');
imgScreen.Stretch := true;
end;
ZApisz obraz, wysylaj kazdy pakiet np. jak jest w przyklad z na kopiowanie plikow poprzez blockwrite 1024 bajty = 1KB array[0..1024]
dokladnie to jest cos takiego:
procedure TForm1.Button2Click(Sender: TObject);
var
f : file;
i : integer;
i2 : integer;
SrcF : file;
s : string;
RealSize : Integer; // realna odczytana wartość z pliku
Buffer : array[0..Count] of char; // bufor przesyłanych danych
TotalSize : Integer;
begin
Totalsize := 0;
AssignFile(SrcF, plik);
AssignFile(F, plik+'imo');
rewrite(f,1);
reset(SrcF,1);
Seek(SrcF, TotalSize);
s := edit1.text;
application.ProcessMessages;
repeat
BlockRead(SrcF, Buffer, SizeOf(Buffer), RealSize);
if RealSize > 0 then
begin
blockwrite(f,Buffer, RealSize);
TotalSize := TotalSize + RealSize;
end;
until RealSize = 0;
blockwrite(f,s,sizeof(s));
closefile(SrcF);
closefile(F);
end;
serwer - wysylasz wiadomosc ze chces przeslac obraz
klient - to odbiera i przesiada sie na tryb przesylania z kazdym pakietemn najlepiej przeslac rekord
type x= record
komenda : //tutaj to moze byc string i go bym polecal w wartosci np. string[25] na wlasne komendy
bajty:array[0..zakres] of byte;
end;
Huh... dobry pomysł... Ja korzystalem z czegos takiego
type TPackage = record
cmd : string[255];
cmdparam : array[1..5] of string[255];
data : array[0..1024] of byte; // w oryginale tego nie ma, stworzone na potrzeby tego posta
end;
(** FAR, FAR AWAY **)
clientsocket1.Socket.SendBuf(package,sizeof(package));
(** REALLY FAR AWAY (Server) **)
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var Package = TPackage;
begin
socket.ReceiveBuf(Package,socket.ReceiveLength);
end;
No i tu moja wiedza się wyczerpała, gdyż mniej więcej w tym momencie pisania troja*a, przesiadłem się na dwa protokoły (tcp i tftp).
dziekuje za odpowiedzi :) teraz na pewno cos wykombinuje z tym jpg :) mam jeszcze jedno male pytanie... jak mozna zwiekszyc ilosc znakow przesylanych przez :
ClientSocket1.Socket.SendText(edit2.Text);
teraz mam tylko jakies 30... :( a przydaloby sie duzo wiecej...
Serwer:
uses Sockets, JPEG;
//..
var Server:TTCPServer;
procedure TForm1.FormCreate(Sender: TObject);
begin
Server:=TTCPServer.Create(self);
Server.LocalPort:='1234';
Server.Active:=TRUE;
Server.OnAccept:=TcpServerAccept;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Server.Free;
end;
procedure TForm1.TcpServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
var Size:integer;
Stream:TMemoryStream;
Komenda:integer;
Canvas:TCanvas;
Bitmap:TBitmap;
Jpeg:TJpegImage;
begin
if (ClientSocket.ReceiveBuf(Komenda, sizeof(Komenda))=sizeof(Komenda)) then
begin
Stream:=TMemoryStream.Create();
Canvas:=TCanvas.Create();
Canvas.Handle:=GetWindowDC(GetDesktopWindow());
Bitmap:=TBitmap.Create;
Bitmap.Width:=Screen.Width;
Bitmap.Height:=Screen.Height;
Bitmap.Canvas.CopyRect(Rect(0,0,Screen.Width,Screen.Height),Canvas,Rect(0,0,Screen.Width,Screen.Height));
Canvas.Free;
Jpeg:=TJpegImage.Create();
Jpeg.CompressionQuality:=80;
Jpeg.Assign(Bitmap);
Bitmap.Free;
Jpeg.Compress;
Jpeg.SaveToStream(Stream);
Jpeg.Free;
Size:=Stream.Size;
if (ClientSocket.SendBuf(Size, sizeof(Size))=sizeof(Size))
and (Size>0) then
ClientSocket.SendBuf(PByte(Stream.Memory)^, Size);
Stream.Free;
end;
end;
Klient:
procedure TForm1.Button1Click(Sender: TObject);
var Client:TTCPClient;
Size:integer;
Stream:TMemoryStream;
Komenda:integer;
begin
Client:=TTCPClient.Create(self);
Client.RemoteHost:='localhost';
Client.RemotePort:='1234';
Client.Active:=TRUE;
Komenda:=0;
if (Client.SendBuf(Komenda, sizeof(Komenda))=sizeof(Komenda))
and (Client.ReceiveBuf(Size, sizeof(Size))=sizeof(Size))
and (Size>0) then
begin
Stream:=TMemoryStream.Create;
Stream.SetSize(Size);
if (Client.ReceiveBuf(PByte(Stream.Memory)^, Size)=Size) then
Stream.SaveToFile('c:\plik.jpg');
Stream.Free;
end;
Client.Free;
end;
Polecam zabezpieczyć funkcje Send/Receive za pomocą pętli, bo może się okazać, że wykonując się przeczytają tylko fragment wysłanego pliku, więc, póki funkcje te nie zwrócą wartości ujemnej lub zera (chyba, że pobrały już całość rozmiaru pliku) trzeba je ponownie wywoływać - taka już zaleta przesyłania większych danych po TCP/IP.
Damian997 napisał(a)
dziekuje za odpowiedzi :) teraz na pewno cos wykombinuje z tym jpg :) mam jeszcze jedno male pytanie... jak mozna zwiekszyc ilosc znakow przesylanych przez :
ClientSocket1.Socket.SendText(edit2.Text);
teraz mam tylko jakies 30... :( a przydaloby sie duzo wiecej...
Ja tam wysyłam znacznie więcej znaków, jakoś mi nie blokuje... Na bank mi przesyła takie coś jak
Socket.SendText(lowercase(Command)+#31+param1+#31+param2+#31+param3+#31+param4+#31+param5+#31);
A czasem tych parametrów mam całkiem sporo, np. ścieżki dostępu do programów i takie tam.
juz wiem gdzie lezy problem... do klienta dochodza pelnej dlugosci zdania... problem zaczyna sie gdy tekst rozdzielam na dwie czesci, poniewaz przesylam jednym ciagiem dwa teksty rozdzielone separatorem '|'
wysylam z servera
serverSocket1.Socket.Connections[serversocket1.Socket.ActiveConnections -1].SendText(lowercase(screen+'|'+dfsgkjgdfjkdsfjdsgfjhg123sdfjhdsgfjhdfjhdsf456fgdfhfhdhdjghjjdfhd789));
program wyglada tak:
function RozdzielString(const AString: string; const Separator:Char; SList:TStringList): integer;
var
CurPos, PrevPos: integer;
Tmp: string;
begin
Result := 0;
CurPos := 0;
repeat
PrevPos := Succ(CurPos);
CurPos := PosEx(Separator,AString,PrevPos);
inc(Result);
if SList<> nil then
begin
if CurPos = 0 then Tmp := Copy(AString,PrevPos,Length(AString))
else Tmp := Copy(AString,PrevPos,CurPos-PrevPos);
SList.Add(Tmp);
end;
until CurPos = 0;
end;
Wywoluje
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
odpowiedz:string;
begin
odpowiedz:=Socket.ReceiveText;
Lista := TStringList.Create;
RozdzielString(odpowiedz, '|', Lista);
Memo1.Lines.Assign(Lista);
Lista.Free;
a1:=memo1.Lines.Strings[0];
b1:=memo1.Lines.Strings[1];
c1:=memo1.Lines.Strings[2];
...
a1 i b1 to dwa rozne teksty... i co tutaj jest nie tak, ze wartosci po rozdzieleniu sa przycinane ?
wie ktos cos ? :)
ja dałem coś takiego:
PS. Znak #31 jest rozdzielaczem.
var
cmd : string;
lparam : string;
rparam : string;
param3,param4,param5 : string;
s : string;
begin
s := Socket.ReceiveText;
(* Procedura odczytu komendy i parametrów *)
try
cmd := copy(s,1,pos(#31,s)-1); // wydziel komendę
delete(s,1,pos(#31,s));
lparam := copy(s,1,pos(#31,s)-1); // wydziel lewy parametr (1)
delete(s,1,pos(#31,s));
rparam := copy(s,1,pos(#31,s)-1); // wydziel prawy parametr (2)
delete(s,1,pos(#31,s));
param3 := copy(s,1,pos(#31,s)-1); // wydziel 3 parametr
delete(s,1,pos(#31,s));
param4 := copy(s,0,pos(#31,s)-1); // wydziel 4 parametr
delete(s,1,pos(#31,s));
param5 := copy(s,1,pos(#31,s)-1); // wydziel 5 parametr
delete(s,1,pos(#31,s));
except
(* END *)
end;
ooo mozna by spróbować takiego sposobu :) tylko powiedz jeszcze w jaki sposob wyslac teksty/zmienne aby to zadzialalo ? i jak to rozpoznaje gdzie sie koncza i zaczynaja zmienne ?
na www.delphi.about.com wpisz w wyszukiwarke ScreenThief i tam masz do pobrania kod zrodlowy do programu ktory robi screeny wysyla liste screenow do klienta a klient moze pobrac dowolny screen z servera.. potrzebne komponenty to Indy min. w wersji 9
Wysyłanie pakietu:
procedure TMainForm.SendCmdP(Command : string; param1 : string = ''; param2 : string = ''; param3 : string = ''; param4 : string = ''; param5 : string ='');
begin
Client.Socket.SendText(lowercase(Command)+#31+param1+#31+param2+#31+param3+#31+param4+#31+param5);
sleep(10);
Application.ProcessMessages;
LogIt(lowercase(Command)+#31+param1+#31+param2+#31+param3+#31+param4+#31+param5,MM_ECHO);
end;
jeszcze raz odbieranie pakietu:
var
cmd : string;
lparam : string;
rparam : string;
param3,param4,param5 : string;
s : string;
begin
s := Socket.ReceiveText;
(* Procedura odczytu komendy i parametrów *)
try
cmd := copy(s,1,pos(#31,s)-1); // wydziel komendę
delete(s,1,pos(#31,s));
lparam := copy(s,1,pos(#31,s)-1); // wydziel lewy parametr (1)
delete(s,1,pos(#31,s));
rparam := copy(s,1,pos(#31,s)-1); // wydziel prawy parametr (2)
delete(s,1,pos(#31,s));
param3 := copy(s,1,pos(#31,s)-1); // wydziel 3 parametr
delete(s,1,pos(#31,s));
param4 := copy(s,0,pos(#31,s)-1); // wydziel 4 parametr
delete(s,1,pos(#31,s));
param5 := copy(s,1,pos(#31,s)-1); // wydziel 5 parametr
delete(s,1,pos(#31,s));
except
(* END *)
end;
Od razu mówię... sam mógłbyś na to wpaść. Daję ci te kody źródłowe tylko dlatego, że znam lepsze sposoby, o wiele prostsze.
lepsze ? prostrze ? mozesz cos wiecej powiedziec ? :)
hmmm... moglbys troche wyjasnic...
procedure TMainForm.SendCmdP(Command : string; param1 : string = ''; param2 : string = ''; param3 : string = ''; param4 : string = ''; param5 : string ='');
co to ? i co z tym zrobic ?
oraz
sleep(10);
Application.ProcessMessages;
LogIt(lowercase(Command)+#31+param1+#31+param2+#31+param3+#31+param4+#31+param5,MM_ECHO);
end;
co to wlasciwie robi ?
cos do uses trzeba dodac ?
To jest procedura zrobiona na potrzeby konia trojańskiego... i jest banalnie prosta. Przyjrzyj sie jej dokładniej. Jeżeli nie możesz jej zlapać, spróbuj pokombinować sam, gdyż mi już sił brakuje...
A o jednym zapomniałem:
sleep(10);
Application.ProcessMessages;
LogIt(lowercase(Command)+#31+param1+#31+param2+#31+param3+#31+param4+#31+param5,MM_ECHO);
end;
Tutaj procedura logIt jest zbędna, ponieważ została napisana prze'ze mnie specjalnie na moje wymagania. Równie dobrze może to być po prostu tak:
sleep(10);
Application.ProcessMessages;
end;
Natomiast Application.ProcessMessages jest tutaj bardzo istotna i teoretycznie najbardziej podstawowa dla każdego programisty.
hmmm a dlaczego program ma zatrzymac swoje dzialanie ?? sleep(10) ??
i co to znaczy Application.ProcessMessages; ??</b>
jak to sobie usune to cos sie stanie ?
Nie, nic się nie stanie. Ten fragment jest tak dla jaj umieszczony :]
- sleep jest po to, żeby wysyłane dane nie zlały się w jeden duży blok, mówiąc z cudzysłowie, tylko żeby były wysyłane oddzielnie i odbierane oddzielnie
- ProcessMessages jest po to, żeby po każdym sleepie aplikacja reagowała na komunikaty, które dostała w czasie "drzemki"