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 Cyfrowy Baron » sobota, 9 października 2010, 11:05

polymorphism napisał(a):Tworzenie ścieżki w tym miejscu to chyba niezbyt dobry pomysł, ponieważ to zdarzenie może być wywoływane wiele razy dla jednego pliku. Wystarczy przenieść to do warunku, gdzie tworzony jest strumień fl.


Nie spowoduje to błędu, ale umieszczenie w warunku rzeczywiście jest lepszym rozwiązaniem.


polymorphism napisał(a):W sumie to nie wiem, po co te zabawy ze strumieniem plikowym i zapisywaniem do pliku, przecież można to zrobić w pamięci, przy pomocy strumienia pamięciowego,


proponowałem to już wcześniej, ale operowanie na dużych plikach w pamięci, lub wielu małych wymaga odpowiedniej ilości pamięci. Tak czy owak to chyba jednak nie rozwiązuje do końca problemu.


polymorphism napisał(a):@gregor, w jakim trybie pracują sockety, blokującym czy nieblokującym?


Kiedyś napisałem prosty komunikator na socketach, ale nie znam ich zbyt dobrze, niemniej jednak nie wiem o co pytasz, więc gregor raczej też nie będzie tego wiedział.


polymorphism napisał(a):p.s. Baron, jak poprawiasz kod, rób to z aktualną wersją.


W żadnym poście nie ma pełnego nowego kodu, więc skopiowałem co jest by pokazać o co mi mniej więcej chodzi.



Nie odniosłeś się w żaden sposób do moich wątpliwości odnośnie Timer'a!
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 » sobota, 9 października 2010, 11:37

proponowałem to już wcześniej, ale operowanie na dużych plikach w pamięci, lub wielu małych wymaga odpowiedniej ilości pamięci.

Mowa o zrzutach ekranu, i to po skompresowaniu, więc pliki duże nie będą.

niemniej jednak nie wiem o co pytasz, więc gregor raczej też nie będzie tego wiedział.

Właściwość TClientWinSocket::ClientType, TServerWinSocket::ServerType.

W żadnym poście nie ma pełnego nowego kodu, więc skopiowałem co jest by pokazać o co mi mniej więcej chodzi.

Rozumiem, ale mimo wszystko lepiej uwzględniać poprawki, bo później robi się chaos. Zresztą do tego, co chciałeś pokazać, nie trzeba było całego kodu, wystarczyłoby wskazać tylko te fragmenty, które uległy zmianie.

Nie odniosłeś się w żaden sposób do moich wątpliwości odnośnie Timer'a!

O timerze pisałem w tym poscie, tłumacząc, dlaczego usunąłem ProcessMessages z pętli wysyłającej plik.
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 » sobota, 9 października 2010, 11:40

polymorphism napisał(a):O timerze pisałem w tym poscie, tłumacząc, dlaczego usunąłem ProcessMessages z pętli wysyłającej plik.


Tylko czy to wystarczy, czy sama pętla jest w stanie zatrzymać zegar, czy może tylko generuje pewne opóźnienie. Czy w przypadku zdarzenia OnTimer, by wystąpił kolejny cykl, funkcja musi dojść do końca?
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 » sobota, 9 października 2010, 11:53

Tak, musi dojść do końca, ponieważ OnTimer jest generowany w obsłudze komunikatu WM_TIMER, który jest odbierany z głównej pętli komunikatów aplikacji.
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 » sobota, 9 października 2010, 12:01

Więc już nie wiem w czym tkwi problem. Pliki są wysyłane kolejno i kolejno odbierane. Jeżeli przed odebraniem kolejnego pliku wszystkie zmienne zostaną wyzerowane, to teoretycznie powinien zacząć się kolejny cykl. Chyba że sockety pozostają z jakiegoś powodu otwarte i serwer cały czas czeka na kolejną porcje danych, czy coś w tym stylu. Nie przemyślałem jeszcze tego dobrze.
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 » sobota, 9 października 2010, 12:16

Według mnie opcje są dwie:
  • sockety nie zachowują się tak, jak to sobie założyłem (i zapewne autor wątku też) - m.in kwestia blokowania. Kody, które podałem, pisane były z myślą o (win)socketach pracujących w trybie blokującym.
  • diagnoza stawiana przez gregora jest błędna.
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 » sobota, 9 października 2010, 12:50

Może więc wystarczy ustawić tryb blokujący, gdyż TServerSocket posiada funkcję ServerType, a TClientSocket funkcję ClientType. Domyślnie te funkcje są ustawione na stNonBlocking, można je ustawić na: ClientType - ctBlocking i ServerType - stThreadBlocking.

sockets.png
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
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 gregor » sobota, 9 października 2010, 13:24

polymorphism napisał(a):
To chyba znaczy, że jest to niewykonalne (albo ja jeszcze za mało potrafię )

Opcja numer dwa ;)

Szczery jesteś, to dobrze 8-)

Cyfrowy Baron
Sprawdziłem działanie kodu z Twojego postu

I już myślałem, że działa poprawnie :geek: a tu przy 10 zdjęciu odebranym przez program serwer zdjęcie było do połowy puste powstał jakiś wyciek danych i następne zdjęcia już tylko były z programu klient (zrzuty ekranu) a serwer nie zapisywał żadnych zdjęć.


Cyfrowy Baron napisał(a):W żadnym poście nie ma pełnego nowego kodu, więc skopiowałem co jest by pokazać o co mi mniej więcej chodzi.

Kod źródłowy:
Serwer
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit6.h"
#include <algorithm>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm6 *Form6;
//zmeinne

  //int fHandle = 0;
  //String  fileName = "c:\\222.jpg";
  TFileStream *fl;
  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)
{
 static int fNr = 0;
 String fileName = ExtractFilePath( ParamStr(0) ) + "file_SER" + (String)fNr + ".jpg";

  if (fl)
  {
    char buf[1024];
                //int size = Socket->ReceiveBuf(buf,1024);
                int size = Socket->ReceiveBuf(buf,std::min<int>(1024,wielkoscpliku - odebranowszystko));
        if(size == -1)return;
        fl->WriteBuffer(buf,size);
                odebranowszystko += size;

                if(odebranowszystko == wielkoscpliku)
        {
                delete fl;
                fl = NULL;
                           fNr += 1;

        }
}
else
{
        if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
        {
                odebranowszystko = 0;
                                fl = new TFileStream( fileName, fmCreate ); // <-- tutaj zmieniłem
        }
}
//============================stare===========================================
 /*
//po kilku zdjeciach przestaje dzialac i pliki sa bez obrazu i w ciaglym urzyciu przez aplikacje
  if (fHandle != 0)
  {
        char buf[1024];
        //int size = Socket->ReceiveBuf(buf,1024);
        int size = Socket->ReceiveBuf(buf,std::min<int>(1024,wielkoscpliku - odebranowszystko));
        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);
        }
}
  */


}
//---------------------------------------------------------------------------

void __fastcall TForm6::Button1Click(TObject *Sender)
{
  //==================
           //    for(int x = 0; x < ServerSocket1->Socket->ActiveConnections; x++)
  //{
  // ServerSocket1->Socket->Connections[x]->SendText("1");
  // Memo1->Text=("Ządanie o sreena");
  //}
  //========================

}
//---------------------------------------------------------------------------
 

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


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

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

{

//====================================stary kod z piatku============================
//Memo1->Lines->Add(Socket->ReceiveText());
//Memo2->Lines->Add(Socket->ReceiveText());
//wiadomosc1 = Socket->ReceiveText();
//Memo1->Lines->Add(">1");
//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((char*)&max,sizeof(long));

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


//Memo1->Lines->Add(wiadomosc1+" wiadomoscB");
//Memo1->Lines->Add(komunikat1+" komunikatB");

//}  //if
}
//---------------------------------------------------------------------------
void __fastcall TForm7::Timer1Timer(TObject *Sender)
{
//Timer1 ustawiony na 10s
  static int fNr = 0;
  char bufor[1024];

  String fileName = ExtractFilePath( ParamStr(0) ) + "file_" + (String)fNr + ".jpg";

 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( fileName ); // <-- tutaj zmieniłem
  ReleaseDC(0, pCanvas->Handle);
  delete pCanvas, Bmp;

TFileStream *fl = new TFileStream( fileName, fmOpenRead ); // <-- tutaj zmieniłem
 int razem = 0, rozmiar = 0 , max = fl->Size;
ClientSocket1->Socket->SendBuf(&max,sizeof(int));

 Timer1->Enabled = false; // zatrzymanie zegara
  do
  {
                rozmiar = fl->Read(bufor,1024);
        razem += rozmiar;
                ClientSocket1->Socket->SendBuf(bufor,rozmiar);
        Application->ProcessMessages();
  } while (razem < max);

 delete fl;
 fNr += 1;
 Timer1->Enabled = true; // uruchomienie zegara.
//====================================stary kod z piatku============================
/*
//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((char*)&max,sizeof(long));

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

Memo1->Lines->Add(wiadomosc1+" wiadomoscB");
Memo1->Lines->Add(komunikat1+" komunikatB");
*/


}
//---------------------------------------------------------------------------
 


polymorphism napisał(a):W sumie to nie wiem, po co te zabawy ze strumieniem plikowym i zapisywaniem do pliku, przecież można to zrobić w pamięci, przy pomocy strumienia pamięciowego, co upraszcza jeszcze bardziej kod klienta:

Zaraz się za to wezmę by to sprawdzić.

polymorphism napisał(a): @gregor, w jakim trybie pracują sockety, blokującym czy nieblokującym?


TClientWinSocket::ClientType ctNonBlocking
TServerWinSocket::ServerTypest NonBlocking






Idea programów:
Klient:
Zrzut ekranu kompresja (waga około 80kb) (nie potrzebny zapis na dysk twardy) wysyła do serwera
Serwer:
Odbiera plik zapisuje na dysk

Zapisałem to w Timer bo chciałem żeby to było wykonywane samodzielnie najlepiej co 3s nowy zrzut może być częściej ale nie wiem czy to nie za bardzo by zaabsorbowało zasoby obliczeniowe komputera?
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 polymorphism » sobota, 9 października 2010, 13:56

Ustaw na tryb blokujący, tak jak pokazał Baron. Myślę, że to tu tkwi problem.

Jeśli chodzi o kod, uwzględnij rzeczy, o których pisałem wcześniej.
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 » sobota, 9 października 2010, 14:13

Strasznie zamotałeś z tym kodem. Mam wrażenie, że wykomentowałeś nie tylko kod stary, ale i część nowego, jak chociażby funkcję SendExact. Trudno to czytać. Jeżeli nie chcesz tracić starego kodu, to zrób kopię zapasową plików *.cpp i *.h ewentualnie jeszcze *.dfm, ale nie trzymaj takich długich komentarzy, gdyż to tylko zaciemnia kod.
Zrób jak radzi polymorphism, czyli ostatnie zmiany i włącz tryb blokujący.
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 gregor » sobota, 9 października 2010, 16:08

W klient
(zamiast w Timer) ClientSocket1Read
Gdy klient dostanie wiadomość „1” od serwera to klient robi zrzut i wysyła go do serwera
Dodałem Sleep bo inaczej wysyła i robi zrzuty z prędkością pętli raz tak puściłem to wszystkie zrzuty zostały zrobione i przesłane do serwera prawidłowo tylko że to trwało 2s gdy doszło do 55 zrzutów to dostałem taki komunikat od programu klient:
„W magazynie brak miejsca dla wykonania tego polecenia”
Jaki magazyn?

Z przerwami po 5s (Sleep) dochodzi do kilku zrzutów i się psuje tak jak wcześniej
Tak to wygląda gdy serwerSocket i clientSocket jest nie blokowany

A gdy mam włączone blokady to nie działa (nie komunikują się)

serwer
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit6.h"
#include <algorithm>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm6 *Form6;
//zmeinne
  TFileStream *fl;
  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)
{
 static int fNr = 0;
 String fileName = ExtractFilePath( ParamStr(0) ) + "file_SER" + (String)fNr + ".jpg";

  if (fl)
  {
    char buf[1024];
                //int size = Socket->ReceiveBuf(buf,1024);
                int size = Socket->ReceiveBuf(buf,std::min<int>(1024,wielkoscpliku - odebranowszystko));
        if(size == -1)return;
        fl->WriteBuffer(buf,size);
                odebranowszystko += size;

                if(odebranowszystko == wielkoscpliku)
        {
                delete fl;
                fl = NULL;
                                fNr += 1;
                                Sleep(5000);
                                        //==================     wysyla powiadomienie o dostarczeniu pliku
                                        for(int x = 0; x < ServerSocket1->Socket->ActiveConnections; x++)
                                        {
                                         ServerSocket1->Socket->Connections[x]->SendText("1");
                                         Memo1->Lines->Add("Żądanie o sreena");
                                        }
                                        //========================

        }
}
else
{
        if(Socket->ReceiveBuf(&wielkoscpliku,sizeof(long)) == sizeof(long) && wielkoscpliku > 0)
        {
                odebranowszystko = 0;
                                fl = new TFileStream( fileName, fmCreate ); // <-- tutaj zmieniłem
        }
}


}
//---------------------------------------------------------------------------

void __fastcall TForm6::Button1Click(TObject *Sender)
{
  //==================  zadanie o zrzut ekranu
                 for(int x = 0; x < ServerSocket1->Socket->ActiveConnections; x++)
  {
   ServerSocket1->Socket->Connections[x]->SendText("1");
   Memo1->Lines->Add("Żądanie o sreena");
  }
  //========================

}
//---------------------------------------------------------------------------



 


klient
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
String komunikat1 = "1";
String wiadomosc1 = "0";
 static int fNr = 0;
 String fileName = ExtractFilePath( ParamStr(0) ) + "file_" + (String)fNr + ".jpg";
//---------------------------------------------------------------------------
__fastcall TForm7::TForm7(TComponent* Owner)
        : TForm(Owner)
{
 AnsiString tekstip = Edit1->Text;
 ClientSocket1->Active = false;
 ClientSocket1->Host = tekstip;
 ClientSocket1->Active = true;
}
//---------------------------------------------------------------------------
//metoda
void TForm7::SendExact(const char *p, unsigned size)
{
                while(size)
                {
                                                                unsigned sent = ClientSocket1->Socket->SendBuf((void*)p,size);
                                p += sent;
                                                                size -= sent;
                }
}
//---------------------------------------------------------------------------
void __fastcall TForm7::ClientSocket1Read(TObject *Sender, TCustomWinSocket *Socket)
{
wiadomosc1 = Socket->ReceiveText();
Memo1->Lines->Add("->1");
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;//ostrość jakość
  jpegImg->Assign(Bmp);
  jpegImg->SaveToFile( fileName ); // <-- tutaj zmieniłem
  ReleaseDC(0, pCanvas->Handle);
  delete pCanvas, Bmp;

//wysyla plik ---
char bufor[1024];


TFileStream *fl = new TFileStream(fileName, fmOpenRead);
long razem = 0, rozmiar = 0 , max = fl->Size;

SendExact((char*)&max,sizeof(long));

while (razem < max)
{
                rozmiar = fl->Read(bufor,1024);
                SendExact(bufor,rozmiar);
                razem += rozmiar;
}
delete fl;
fNr += 1;
wiadomosc1 = "0";
}  //if
}
//---------------------------------------------------------------------------
void __fastcall TForm7::FormCreate(TObject *Sender)
{

}
//---------------------------------------------------------------------------
 



Pliki źródłowe: (w serwer pierwszy zrzut wysyła po wciśnięciu „Pobieraj zrzut od klienta”)
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
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 polymorphism » sobota, 9 października 2010, 16:48

Dobra, jeśli na blokującym w ogóle nie działa, to może wróćmy do trybu nieblokującego.



(...) gdy doszło do 55 zrzutów to dostałem taki komunikat od programu klient: „W magazynie brak miejsca dla wykonania tego polecenia”

KOD cpp:     UKRYJ  
delete pCanvas, Bmp;

Skąd Ty te konstrukcje bierzesz?! Zmień to na:
KOD cpp:     UKRYJ  
delete pCanvas;
delete Bmp;

A najlepiej użyj auto_ptr...
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 » sobota, 9 października 2010, 16:51

Skąd Ty te konstrukcje bierzesz?! Zmień to na:


Pewnie z mojej strony http://cyfbar.republika.pl
Kiedyś zamieściłem coś takiego, nie poprawiłem i już tak zostało.

Powstaje wyciek pamięci, gdyż obiekt bmp nie jest kasowany. Tutaj można by użyć wzorca klasy auto_ptr do wszystkich obiektów, wtedy same by po sobie sprzątały.
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 Cyfrowy Baron » niedziela, 10 października 2010, 11:47

Wziąłem się za analizowanie Twojego projektu z załącznika i już na samym początku wywołał on u mnie rozdrażnienie. Nie stosujesz się do zaleceń, jakie tutaj Tobie podajemy.

Po pierwsze w programie Klient zmienną statyczną fNr umieściłem w zdarzeniu OnTimer podobnie jak zmienną fileName, a ty uczyniłeś z nich zmienne globalne. Tworzenie globalnej zmiennej statycznej jest pozbawione sensu, ponieważ w C++ każda zmienna globalna jest zmienną statyczną. Zmienna statyczna to taka zmienna, która w danym bloku programu posiada dokładnie jedną instancję i istnieje przez cały czas działania programu, i mimo tego, iż jest zadeklarowana wewnątrz zdarzenia, a zdarzenie jest wielokrotnie wywoływane to instancja tej zmiennej nie zmienia się i po zakończeniu zdarzenia zmienna nie znika. Zmienna statyczna zachowuje się jak zmienna globalna z tą różnicą, że jej instancja jest ograniczona do funkcji, w której została zadeklarowana.
Po wtóre zmienna fileName może być zmienną globalna, ale ta zmienna ma za zadanie przechowywać nazwę pliku z kolejnym zmieniającym się numerem. Czyli w każdym cyklu zegara, ta zmienna miała przechowywać inną wartość określającą nazwę pliku, więc zmiana tej wartości musi występować w tym zdarzeniu. Tak jak ty to zrobiłeś, jest pozbawione sensu, gdyż mimo tego, iż zmienia się wartość zmiennej fNr, to zmienna fileName nie ulega zmianie.


Na razie tyle uwag.
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

Wysyłanie i odbieranie plików TServerSocket, TClientSocket

Nowy postprzez Cyfrowy Baron » niedziela, 10 października 2010, 13:51

Wydaje mi się, że znalazłem przyczynę błędu. Przeprowadziłem kilka testów i w ostatecznym rozrachunku przesłałem trzykrotnie po ponad 100 plików bezbłędnie, w ostatnim przypadku ponad 200.

Przede wszystkim zrezygnowałem z klasy TFileStream w programie KLIENT i zastąpiłem ją klasą TMemoryStream, dzięki czemu klient nie zapisuje plików na dysku, a gdyby nawet musiał to ta klasa też to potrafi.

Błąd udało mi się wyeliminować, gdy wprowadziłem niewielkie opóźnienie w tej pętli:

KOD cpp:     UKRYJ  
 while(razem < max)
 {
   rozmiar = mStream->Read(bufor, 1024);

   Sleep(10);

   SendExact(bufor, rozmiar);
   razem += rozmiar;
 }
Jednocześnie ustawiłem interwał czasu w zegarze na 1 sekundę, więc pliki są przesyłane w kilka sekund.
Kolejna sprawa, to nie testuj tych programów w środowisku C++Builder, lecz uruchom je normalnie. Ustaw typ kompilacji na Release.

KLIENT - plik nagłówkowy Unit7.h:
KOD cpp:     UKRYJ  
private:
     void SendExact(const char *p, unsigned size);


KLIENT - plik źródłowy Unit7.cpp:
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;

//---------------------------------------------------------------------------
__fastcall TForm7::TForm7(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void TForm7::SendExact(const char *p, unsigned size)
{
 while(size)
 {
  unsigned sent = ClientSocket1->Socket->SendBuf((void*)p, size);
  p += sent;
  size -= sent;
 }
}
//---------------------------------------------------------------------------
void __fastcall TForm7::Button1Click(TObject *Sender)
{
 ClientSocket1->Active = true;
 Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall ScreenCapture(TMemoryStream *mStream)
{
  std::auto_ptr<TCanvas> pCanvas(new TCanvas());
  std::auto_ptr<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.get(), Rect(0, 0, Bmp->Width, Bmp->Height));

  std::auto_ptr<TJPEGImage> jpegImg(new TJPEGImage());
  jpegImg->CompressionQuality = 20;
  jpegImg->Assign(Bmp.get());

  jpegImg->SaveToStream(mStream);
  ReleaseDC(0, pCanvas->Handle);
}
//---------------------------------------------------------------------------
void __fastcall TForm7::Timer1Timer(TObject *Sender)
{
 //zapisuje do jpg  zrzutu ekranu
 TMemoryStream *mStream = new TMemoryStream();

 ScreenCapture(mStream);

 //wysyla plik ---
 char bufor[1024];
 mStream->Position = 0;
 long razem = 0, rozmiar = 0 , max = mStream->Size;

 SendExact((char*)&max, sizeof(long));

 while(razem < max)
 {
   rozmiar = mStream->Read(bufor, 1024);
   Sleep(10);
   SendExact(bufor, rozmiar);
   razem += rozmiar;
 }
 delete mStream;
}
//---------------------------------------------------------------------------




SERWER - plik nagłówkowy Unit6.h:
KOD cpp:     UKRYJ  
private:
  TFileStream *fl;
  long wielkoscpliku, odebranowszystko;



SERWER - plik źródłowy Unit7.cpp:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit6.h"
#include <algorithm>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm6 *Form6;


//---------------------------------------------------------------------------
__fastcall TForm6::TForm6(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm6::FormShow(TObject *Sender)
{
 Application->MessageBox(L"Odebrane pliki będą przechowywane w podkatalogu "
 "'screen', w katalogu aplikacji", Application->Title.t_str(),
   MB_OK | MB_ICONINFORMATION);
}
//---------------------------------------------------------------------------
void __fastcall TForm6::FormCreate(TObject *Sender)
{
 String dirScreen = ExtractFilePath( ParamStr(0) ) + "screens";
 if(!DirectoryExists(dirScreen)) CreateDir(dirScreen.t_str());
 ServerSocket1->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm6::ServerSocket1ClientRead(TObject *Sender,
        TCustomWinSocket *Socket)
{
 static int fNr = 0;
 String fileName = ExtractFilePath( ParamStr(0) ) + "screens\\file_" + (String)fNr + ".jpg";

 if(fl)
 {
  char buf[1024];

  int size = Socket->ReceiveBuf(buf, std::min<int>(1024,
                                wielkoscpliku - odebranowszystko));

  if(size == -1)return;

  fl->WriteBuffer(buf, size);
  odebranowszystko += size;

  if(odebranowszystko >= wielkoscpliku)
  {
   delete fl;
   fl = NULL;
   fNr += 1;

  }
 }
 else
 {
  if(Socket->ReceiveBuf(&wielkoscpliku, sizeof(long)) == (int)sizeof(long) &&
     wielkoscpliku > 0)
  {
   odebranowszystko = 0;
   fl = new TFileStream( fileName, fmCreate );
  }
 }
}
//---------------------------------------------------------------------------



Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
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

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 5 gości

cron