CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - socket wysyłanie jpg

socket wysyłanie jpg

problemy z tworzeniem programów do obsługi sieci, internetu, e-mail itp..

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » czwartek, 7 października 2010, 10:33

gdyż z jednej strony odwołujesz się do istniejącego pliku, a z drugiej tworzysz nowy i dlaczego decyduje o tym zmienna przesyl?! Co ta zmienna ma wspólnego z istniejącym plikiem.

Ma to wspólnego, że jeśli będzie true, to oznacza, że strumień f1 został stworzony, ergo proces ściągania pliku został zainicjowany. Jak łatwo zauważyć przesyl jest zmienną nadmiarową, ponieważ tę samą funkcję może pełnić wskaźnik f1:
KOD cpp:     UKRYJ  
if (f1)
{
    char buf[1024];
    int size = Socket->ReceiveBuf(buf,1024);
    if(size == -1)return;
    fl->WriteBuffer(buf,size);
    odebranowszystko += size;

    /* wszystko się ściągnęło, koniec imprezy */
    if(odebranowszystko == wielkoscpliku)
    {
        delete f1;
        f1 = NULL;
    }
}
else
{
    if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
    {
        odebranowszystko = 0;
        fl = new TFileStream("C:\\222.jpg", fmCreate);
    }
}
 

Oczywiście wskaźnik f1 musi być wyzerowany na początku.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez Cyfrowy Baron » czwartek, 7 października 2010, 11:48

Ok! Teraz rozumiem. Twój kod rzeczywiście rozwiązuje problem, gdyż usuwanie obiektu f1 umieściłeś w warunku odpowiedzialnym za pobranie całego pliku. Nie przyszło mi to do głowy, zmyliła mnie chyba kolejność warunków - otwieranie pliku przed jego utworzeniem - oczywiście tak to wygląda obrazowo, a może dlatego, że nie analizowałem tego kodu zbyt dokładnie i przyjąłem założenie, że program wykonuje operacje, na dwóch różnych plikach. :? :oops: :(
O ile nie wystąpią jakieś problemy przy odbieraniu pliku, to kod będzie działał prawidłowo, ale co jeżeli nastąpi np. zresetowanie połączenia z siecią w trakcie pobierania pliku. Konieczny będzie restart aplikacji.

Zadanie da się również zrealizować za pomocą proponowanych przeze mnie funkcji:

KOD cpp:     UKRYJ  
String  fileName = "c:\\nazwa_pliku";

BOOL przesyl = false;
int max = 0;
char bufor[8192];
long wielkoscpliku, odebranowszystko;

int fHandle = 0;

//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
        TCustomWinSocket *Socket)
{
  if (fHandle != 0)
  {
    char buf[1024];
    int size = Socket->ReceiveBuf(buf,1024);
    if(size == -1)return;
    FileWrite(fHandle, buf, size);
    odebranowszystko += size;

    /* wszystko się ściągnęło, koniec imprezy */
    if(odebranowszystko == wielkoscpliku)
    {
       FileClose(fHandle);
    }
  }
  else
  {
    if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
    {
        odebranowszystko = 0;
       fHandle = FileCreate(fileName, fmCreate);
    }
  }
}


Problem z zerwanym połączeniem można by rozwiązać w ten sposób, że program przed każdym połączeniem serwera z siecią resetuje uchwyt fHandle poprzez przypisanie wartości 0. Z obiektem klasy TFileStream można by postąpić podobnie, mam jednak wątpliwości czy nie pojawią się tutaj jakieś błędy, jeżeli program będzie próbował usunąć obiekt, który został już usunięty.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » czwartek, 7 października 2010, 12:54

(...) ale co jeżeli nastąpi np. zresetowanie połączenia z siecią w trakcie pobierania pliku. Konieczny będzie restart aplikacji.

Obsługa błędów w kodzie, który podałem, jest śladowa, ponieważ nie było moją intencją pisanie gotowej funkcji, tylko częściowe uporządkowanie kodu, który już istniał. Nie znam socketów VCL-owych, więc za bardzo nie wiem, jak one reagują na błędy. Z dokumentacji wynika, że w zdarzeniu TCustomSocket::OnClientError można usunąć strumień, jeśli będzie jakiś błąd.

Ogólnie rzecz biorąc, nie powinno być jednego globalnego strumienia na serwerze, bo jeśli będzie kilka połączeń, to mamy katastrofę. Każde połączenie powinno mieć przypisany swój własny strumień (mapa ma tu zastosowanie).

Jeśli chodzi o użycie funkcji FileCreate itd., nie widzę korzyści. Lepiej to robić w "C++ way", korzystając z obiektowych odpowiedników strumieni.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez Cyfrowy Baron » czwartek, 7 października 2010, 13:43

No, ale funkcje File... dają prosty i łatwy sposób na obsługę plików i to poprzez jeden uchwyt. Jedyne o co trzeba się martwić to zwolnienie tego uchwytu no i nie ma ryzyka wycieku pamięci.

polymorphism napisał(a):Ogólnie rzecz biorąc, nie powinno być jednego globalnego strumienia na serwerze, bo jeśli będzie kilka połączeń, to mamy katastrofę


Dlatego od początku twierdzę, że ten globalny obiekt typu TFileStream jest kiepskim rozwiązaniem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » czwartek, 7 października 2010, 14:07

No, ale funkcje File... dają prosty i łatwy sposób na obsługę plików i to poprzez jeden uchwyt.

Strumień też, poprzez jeden wskaźnik ;) Poziom trudności użycia funkcji r/w jest taki sam...

Jedyne o co trzeba się martwić to zwolnienie tego uchwytu no i nie ma ryzyka wycieku pamięci.

Ale będzie wyciek zasobu systemowego. Zamknięcie uchwytu pliku jest ekwiwalentne z usunięciem strumienia poprzez delete. Więc jeśli będziesz pamiętał o zwolnieniu uchwytu, to tak samo będziesz pamiętał o usunięciu strumienia. Jeśli zapomnisz, w obu przypadkach masz wyciek. Zresztą od czego są inteligentne wskaźniki...

Weź jeszcze pod uwagę korzyści jakie daje polimorfizm.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez gregor » czwartek, 7 października 2010, 15:48

Cyfrowy Baron napisał(a):gdyż z jednej strony odwołujesz się do istniejącego pliku, a z drugiej tworzysz nowy i dlaczego decyduje o tym zmienna przesyl?! Co ta zmienna ma wspólnego z istniejącym plikiem.


Próbuje na różne sposoby rozwiązać problem a widzę, że jest spory.

Nawet jak już się udało zrobić przesyłanie pliku to po 2-3 razie on przestaje być przesyłany prawidłowo tylko jakieś szczepy.

polymorphism napisał(a):
KOD cpp:     UKRYJ  
if (f1)
{
    char buf[1024];
    int size = Socket->ReceiveBuf(buf,1024);
    if(size == -1)return;
    fl->WriteBuffer(buf,size);
    odebranowszystko += size;

    /* wszystko się ściągnęło, koniec imprezy */
    if(odebranowszystko == wielkoscpliku)
    {
        delete f1;
        f1 = NULL;
    }
}
else
{
    if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
    {
        odebranowszystko = 0;
        fl = new TFileStream("C:\\222.jpg", fmCreate);
    }
}
 


Wszystko działa dobrze ale do czasu bo po kilku plikach już następne nie idą.

Cyfrowy Baron napisał(a):
KOD cpp:     UKRYJ  
String  fileName = "c:\\nazwa_pliku";

BOOL przesyl = false;
int max = 0;
char bufor[8192];
long wielkoscpliku, odebranowszystko;

int fHandle = 0;

//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
        TCustomWinSocket *Socket)
{
  if (fHandle != 0)
  {
    char buf[1024];
    int size = Socket->ReceiveBuf(buf,1024);
    if(size == -1)return;
    FileWrite(fHandle, buf, size);
    odebranowszystko += size;

    /* wszystko się ściągnęło, koniec imprezy */
    if(odebranowszystko == wielkoscpliku)
    {
       FileClose(fHandle);
    }
  }
  else
  {
    if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
    {
        odebranowszystko = 0;
       fHandle = FileCreate(fileName, fmCreate);
    }
  }
}



Też dobrze ale tylko jeden plik przesyła.

Moje próby poprawienia tych kodów wychodzi poza moje aktualne umiejętności. Jak ktoś jest na tyle życzliwy by je poprawić to bym prosił.
Avatar użytkownika
gregor
Bladawiec
Bladawiec
 
Posty: 17
Dołączył(a): wtorek, 5 października 2010, 18:56
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Win XP
Kompilator: RAD Studio 2010
C++
Gadu Gadu: 0
    Windows XPOpera

Re: socket wysyłanie jpg

Nowy postprzez Cyfrowy Baron » czwartek, 7 października 2010, 16:51

Nawet jak już się udało zrobić przesyłanie pliku to po 2-3 razie on przestaje być przesyłany prawidłowo tylko jakieś szczepy.


Trochę to niezwykłe, skoro prawidłowo odbiera 3 pliki, to nie bardzo widzę powodu, dla którego nie miałby prawidłowo odebrać kolejnych. Być może błąd wywołuje inny kod, którego tutaj nie podałeś.

Też dobrze ale tylko jeden plik przesyła.


Chyba trzeba by to zrobić tak:

KOD cpp:     UKRYJ  
    if(odebranowszystko == wielkoscpliku)  {
       FileClose(fHandle);
       fHandle = 0;
    }
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » czwartek, 7 października 2010, 18:10

Wszystko działa dobrze ale do czasu bo po kilku plikach już następne nie idą.

A jak przesyłasz te pliki, na jednym połączeniu, czy dla każdego oddzielne?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez gregor » czwartek, 7 października 2010, 19:18

polymorphism napisał(a):A jak przesyłasz te pliki, na jednym połączeniu, czy dla każdego oddzielne?

Na jednym połączeniu.

Zrobiłem osobne dwa programy ich cały kod podałem poniżej.
Program z ClientSocket robi zrzut ekranu i wysyła plik do ServerSocket on to odbiera i zapisuje na dysku

Jak Client wyśle ponownie zrzut to Serwer nadpisuje poprzedni plik


Client
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit7.h"
#include <JPEG.hpp>
#include <memory>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm7 *Form7;
//zmienne
int max = 0;
char bufor[1024];
//---------------------------------------------------------------------------
__fastcall TForm7::TForm7(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm7::FormCreate(TObject *Sender)
{
 AnsiString tekstip = Edit1->Text;
 ClientSocket1->Active = false;
 ClientSocket1->Host = tekstip;
 ClientSocket1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm7::Timer1Timer(TObject *Sender)
{//Timer1 ustawilem na 30s
 //zapisuje do jpg  zrzutu ekranu
TCanvas *pCanvas = new TCanvas();
Graphics::TBitmap *Bmp = new Graphics::TBitmap;
  pCanvas->Handle = GetDC(0);
  Bmp->Width  = Screen->Width;
  Bmp->Height = Screen->Height;
  Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));
std::auto_ptr<TJPEGImage> jpegImg(new TJPEGImage());
  jpegImg->CompressionQuality = 20;//ostrość jakość
  jpegImg->Assign(Bmp);
jpegImg->SaveToFile("111.jpg");
ReleaseDC(0, pCanvas->Handle);
  delete pCanvas, Bmp;

Sleep(3000);

//wysyla plik --------------------------------+++++++++++++++++++++
                //fl->WriteBuffer(buf,size);
TFileStream *fl = new TFileStream("111.jpg", fmOpenRead);
 int razem = 0, rozmiar = 0 , max = fl->Size;
ClientSocket1->Socket->SendBuf(&max,sizeof(int));
  //ClientSocket1->Socket->SendBuf(&max,4);
  do
  {
        rozmiar = fl->Read(bufor,1024);
        razem += rozmiar;
        ClientSocket1->Socket->SendBuf(bufor,rozmiar);
        Application->ProcessMessages();
  } while (razem < max);

 delete fl;
}
//---------------------------------------------------------------------------
 


Serwer
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit6.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm6 *Form6;
//zmeinne
TFileStream *fl;
  int fHandle = 0;
  String  fileName = "c:\\222.jpg";
long wielkoscpliku, odebranowszystko;
//---------------------------------------------------------------------------
__fastcall TForm6::TForm6(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm6::FormCreate(TObject *Sender)
{
ServerSocket1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm6::ServerSocket1ClientRead(TObject *Sender, TCustomWinSocket *Socket)
{
/*
//po kilku zdjeciach przestaje dzialac i pliki sa bez obrazu i w ciaglym uzyciu przez aplikacje
  if (fHandle != 0)
  {
        char buf[1024];
        int size = Socket->ReceiveBuf(buf,1024);
        if(size == -1)return;
        FileWrite(fHandle, buf, size);
        odebranowszystko += size;

        // wszystko się ściągnęło, koniec imprezy
        if(odebranowszystko == wielkoscpliku)
        {
           FileClose(fHandle);
           fHandle = 0;
        }
  }
  else
  {
        if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
        {
        odebranowszystko = 0;
           fHandle = FileCreate(fileName, fmCreate);
    }
  }    */


 //juz po pierwszym przestaje prawidlowo wysylac pliki
 if (fl)
{
    char buf[1024];
        int size = Socket->ReceiveBuf(buf,1024);
        if(size == -1)return;
        fl->WriteBuffer(buf,size);
        odebranowszystko += size;

        // wszystko się ściągnęło, koniec imprezy
        if(odebranowszystko == wielkoscpliku)
        {
                delete fl;
                fl = NULL;
        }
}
else
{
        if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
        {
                odebranowszystko = 0;
                fl = new TFileStream("C:\\222.jpg", fmCreate);
        }
}


}
//---------------------------------------------------------------------------
 
Avatar użytkownika
gregor
Bladawiec
Bladawiec
 
Posty: 17
Dołączył(a): wtorek, 5 października 2010, 18:56
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Win XP
Kompilator: RAD Studio 2010
C++
Gadu Gadu: 0
    Windows XPOpera

Re: socket wysyłanie jpg

Nowy postprzez Cyfrowy Baron » czwartek, 7 października 2010, 19:30

Ten temat nie jest mi dobrze znany, ale użycie Timer'a wydaje mi się być pomysłem wyjątkowo kiepskim. Sugerowałbym rozwiązanie polegające na tym, że klient wysyła do serwera plik i czeka na odpowiedź od serwera. Serwer plik odbiera i wysyła do klienta powiadomienie, że plik został odebrany, wtedy klient wysyła kolejny plik.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » czwartek, 7 października 2010, 20:49

Na jednym połączeniu.

Zmień:
KOD cpp:     UKRYJ  
int size = Socket->ReceiveBuf(buf,1024);

na:
KOD cpp:     UKRYJ  
#include <algorithm>
...
int size = Socket->ReceiveBuf(buf,std::min<int>(1024,wielkoscpliku - odebranowszystko);


Sugerowałbym rozwiązanie polegające na tym, że klient wysyła do serwera plik i czeka na odpowiedź od serwera.

W TCP/IP takie potwierdzenie nie jest konieczne, raczej sugerowałbym, żeby w razie problemów połączenie było przerwane, a niekompletny plik usuwany.

KOD cpp:     UKRYJ  
Sleep(3000);

A po co to?! Przecież całość idzie w timerze? Ustaw go na 3 sekundy i efekt będzie ten sam.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez gregor » piątek, 8 października 2010, 00:05

Cyfrowy Baron napisał(a):Ten temat nie jest mi dobrze znany, ale użycie Timer'a wydaje mi się być pomysłem wyjątkowo kiepskim. Sugerowałbym rozwiązanie polegające na tym, że klient wysyła do serwera plik i czeka na odpowiedź od serwera. Serwer plik odbiera i wysyła do klienta powiadomienie, że plik został odebrany, wtedy klient wysyła kolejny plik.


Wyjątkowo musze się z tobą zgodzić i tak zrobiłem aczkolwiek nie zmienia to faktu, że nie działa.
Nadal jest ten sam problem opisze go teraz dobrze:
Aplikacja serwer się zawiesza w momencie odczytywania fragmentów pliku (to ma miejsce po kilku wysłanych plikach ich ilość jest różna) widać to po tym, że aplikacja stworzyła plik pusty (bez zdjęcia) i nic więcej nie robi, pliku nie mogę usunąć (ręcznie) bo dostaje komunikat, że plik jest w użyciu dopiero po zamknięciu aplikacji serwer plik jest do mojej dyspozycji i pojawia się w nim jakiś fragment zdjęcia wysyłanego.

polymorphism napisał(a):
Na jednym połączeniu.

Zmień:
KOD cpp:     UKRYJ  
int size = Socket->ReceiveBuf(buf,1024);

na:
KOD cpp:     UKRYJ  
#include <algorithm>
...
int size = Socket->ReceiveBuf(buf,std::min<int>(1024,wielkoscpliku - odebranowszystko);


Sugerowałbym rozwiązanie polegające na tym, że klient wysyła do serwera plik i czeka na odpowiedź od serwera.

W TCP/IP takie potwierdzenie nie jest konieczne, raczej sugerowałbym, żeby w razie problemów połączenie było przerwane, a niekompletny plik usuwany.

KOD cpp:     UKRYJ  
Sleep(3000);

A po co to?! Przecież całość idzie w timerze? Ustaw go na 3 sekundy i efekt będzie ten sam.


Zamiana nic nie daje.

Tylko jak ma aplikacja wykryć ten błąd by mogła podjąć wymienione akcje?

Ten Sleep to oczywiście niepotrzebny jest…

Pozdrawiam
Avatar użytkownika
gregor
Bladawiec
Bladawiec
 
Posty: 17
Dołączył(a): wtorek, 5 października 2010, 18:56
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Win XP
Kompilator: RAD Studio 2010
C++
Gadu Gadu: 0
    Windows XPOpera

Re: socket wysyłanie jpg

Nowy postprzez Cyfrowy Baron » piątek, 8 października 2010, 08:16

gregor napisał(a):Tylko jak ma aplikacja wykryć ten błąd by mogła podjąć wymienione akcje?


Posłuż się zdarzeniem OnClientError.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez polymorphism » piątek, 8 października 2010, 10:03

Po stronie klienta dodaj metodę:
KOD cpp:     UKRYJ  
void SendExact(const char *p, unsigned size)
{
        while(size)
        {
                unsigned sent = ClientSocket1->Socket->SendBuf(p,size);
                p += sent;
                size -= sent;
        }
}

i popraw kod:
KOD cpp:     UKRYJ  
long razem = 0, rozmiar = 0 , max = fl->Size;
char bufor[1024];

SendExact(&max,sizeof(long));

while (razem < max)
{
        rozmiar = fl->Read(bufor,1024);
        SendExact(bufor,rozmiar);
        razem += rozmiar;
}

Użycie ProcessMessages wewnątrz obsługi timera to dość ryzykowne, szczególnie gdy mowa o obsłudze, która może zająć trochę czasu (może dochodzić do wywołań rekurencyjnych).


Zamiana nic nie daje.

Wierz mi, daje. Dzięki niej aplikacja czyta z socketa dokładnie tyle bajtów, ile ma plik, nie więcej. Jest to istotne w przypadku, gdy na jednym połączeniu przesyłasz kilka plików.

_____
p.s. nie cytuj całych postów.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: socket wysyłanie jpg

Nowy postprzez gregor » piątek, 8 października 2010, 11:19

polymorphism napisał(a):Użycie ProcessMessages wewnątrz obsługi timera to dość ryzykowne, szczególnie gdy mowa o obsłudze, która może zająć trochę czasu (może dochodzić do wywołań rekurencyjnych).


Zrezygnowałem z Timera tak jak pisał Cyfrowy Baron i przeniosłem to do ClientSocket OnRead bo tam odbiera wiadomość od ServerSocket, że plik został odebrany następnie robi zrzut ekranu i wysyła kolejne zdjęcie cały kod aplikacji Client podałem poniżej.

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit7.h"
#include <JPEG.hpp>
#include <memory>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm7 *Form7;
//zmienne
int max = 0;
//char bufor[1024];

String komunikat1 = "1";
String wiadomosc1 = "0";

//---------------------------------------------------------------------------
//metoda
 void SendExact(const char *p, unsigned size)
{
                while(size)
                {
                                unsigned sent = ClientSocket1->Socket->SendBuf(p,size);
                                p += sent;
                                size -= sent;
                }
}
//---------------------------------------------------------------------------
__fastcall TForm7::TForm7(TComponent* Owner)
        : TForm(Owner)
{
 AnsiString tekstip = Edit1->Text;
 ClientSocket1->Active = false;
 ClientSocket1->Host = tekstip;
 ClientSocket1->Active = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm7::ClientSocket1Read(TObject *Sender, TCustomWinSocket *Socket)

{
//Memo1->Lines->Add(Socket->ReceiveText());
//Memo2->Lines->Add(Socket->ReceiveText());
wiadomosc1 = Socket->ReceiveText();
Memo1->Lines->Add(wiadomosc1+" wiadomoscA");
Memo1->Lines->Add(komunikat1+" komunikatA");

if (wiadomosc1==komunikat1) {

 //zapisuje do jpg  zrzutu ekranu
TCanvas *pCanvas = new TCanvas();
Graphics::TBitmap *Bmp = new Graphics::TBitmap;
  pCanvas->Handle = GetDC(0);
  Bmp->Width  = Screen->Width;
  Bmp->Height = Screen->Height;
  Bmp->Canvas->CopyRect(Rect(0, 0, Bmp->Width, Bmp->Height), pCanvas, Rect(0, 0, Bmp->Width, Bmp->Height));
std::auto_ptr<TJPEGImage> jpegImg(new TJPEGImage());
  jpegImg->CompressionQuality = 20;
  jpegImg->Assign(Bmp);
jpegImg->SaveToFile("111.jpg");
ReleaseDC(0, pCanvas->Handle);
  delete pCanvas, Bmp;

 /*
//wysyla plik --------------------------------+++++++++++++++++++++
                //fl->WriteBuffer(buf,size);
TFileStream *fl = new TFileStream("111.jpg", fmOpenRead);
 int razem = 0, rozmiar = 0 , max = fl->Size;
ClientSocket1->Socket->SendBuf(&max,sizeof(int));
  //ClientSocket1->Socket->SendBuf(&max,4);
  do
  {
        rozmiar = fl->Read(bufor,1024);
        razem += rozmiar;
        ClientSocket1->Socket->SendBuf(bufor,rozmiar);
        Application->ProcessMessages();
  } while (razem < max);

 delete fl;
 //FileClose(fl->Handle);
 wiadomosc1 = "0";
*/


TFileStream *fl = new TFileStream("111.jpg", fmOpenRead);
long razem = 0, rozmiar = 0 , max = fl->Size;
char bufor[1024];

SendExact(&max,sizeof(long));

while (razem < max)
{
                rozmiar = fl->Read(bufor,1024);
                SendExact(bufor,rozmiar);
                razem += rozmiar;
}
delete fl;
wiadomosc1 = "0";

}  //if
}

//---------------------------------------------------------------------------


 

Dodałem metodę i poprawiłem kod (mam nadzieje, że dobrze to zrobiłem)
Po kompilacji pokazuje mi takie błędy:

Checking project dependencies...
Compiling terminalCLI.cbproj (Debug configuration)
[BCC32 Error] Unit7.cpp(23): E2451 Undefined symbol 'ClientSocket1'
Full parser context
Unit7.cpp(20): parsing: void SendExact(const char *,unsigned int)
[BCC32 Error] Unit7.cpp(88): E2034 Cannot convert 'long *' to 'const char *'
Full parser context
Unit7.cpp(41): parsing: void _fastcall TForm7::ClientSocket1Read(TObject *,TCustomWinSocket *)
[BCC32 Error] Unit7.cpp(88): E2342 Type mismatch in parameter 'p' (wanted 'const char *', got 'long *')
Full parser context
Unit7.cpp(41): parsing: void _fastcall TForm7::ClientSocket1Read(TObject *,TCustomWinSocket *)
Failed
Elapsed time: 00:00:00.5


Ten pierwszy nie wiem dlaczego bo ClientSocet1 istnieje może ja coś schrzaniłem?
Avatar użytkownika
gregor
Bladawiec
Bladawiec
 
Posty: 17
Dołączył(a): wtorek, 5 października 2010, 18:56
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Win XP
Kompilator: RAD Studio 2010
C++
Gadu Gadu: 0
    Windows XPOpera

Poprzednia stronaNastępna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje sieciowe

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 1 gość