przesylanie JPG miedzy ClientSocket <> ServerSocket

0

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) ??

0

na pewno jest w FAQu albo artach gtowe rozwiązanie

0

przejrzalem wszystko... ARTYKULY, FAQ, GOTOWCE i nic nie znalazlem na temat wysylania jpg przez ClientSocket i ServerSocket... :(

0

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>
0

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 ? :)

0

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;
0

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;

0

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).

0

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...

0

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.

0
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.

0

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 ?

0

wie ktos cos ? :)

0

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;
0

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 ?

0

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

0

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.

0

lepsze ? prostrze ? mozesz cos wiecej powiedziec ? :)

0

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 ?

0

cos do uses trzeba dodac ?

0

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.

0

hmmm a dlaczego program ma zatrzymac swoje dzialanie ?? sleep(10) ??

i co to znaczy Application.ProcessMessages; ??</b>

0

jak to sobie usune to cos sie stanie ?

0

Nie, nic się nie stanie. Ten fragment jest tak dla jaj umieszczony :]

  1. 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
  2. ProcessMessages jest po to, żeby po każdym sleepie aplikacja reagowała na komunikaty, które dostała w czasie "drzemki"

0 użytkowników online, w tym zalogowanych: 0, gości: 0