JPG über sockets!



  • was soll das für schrott sein? das sieht voll hässlich aus, hier ist Winapi und kein schrott c++ forum.



  • FILE * pFile;
      long lSize;
      char * buffer;
      size_t result;
    
      pFile = fopen ( "myfile.bin" , "rb" );
      if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
    
      // obtain file size:
      fseek (pFile , 0 , SEEK_END);
      lSize = ftell (pFile);
      rewind (pFile);
    
      // allocate memory to contain the whole file:
      buffer = (char*) malloc (sizeof(char)*lSize);
      if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
    
      // copy the file into the buffer:
      result = fread (buffer,1,lSize,pFile);
      if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
    
      /* the whole file is now loaded in the memory buffer. */
    
      // buffer hier jetzt noch über send verschicken und fertig?
      // enthält buffer die ganze datei oder muss ich mehrere teile schicken?
    
      // terminate
      fclose (pFile);
      free (buffer);
    


  • und wie kann ich dann aus dem empfangegen buffer wieder eine datei erstellen?



  • asdca schrieb:

    hier ist Winapi und kein schrott c++ forum.

    Ob der Thread-Ersteller C oder C++ programmieren will, sei ihm immer noch freigestellt.

    omg schrieb:

    so?
    ifstream file;
    file.open(".jpg",ios::in|ios::binary);

    send(s,file,sizeof(file),0);
    file.close();

    Fast 🙂

    ifstream file( "bla.jpg", ios::binary );
    
    // Dateigröße ermitteln
    file.seekg( 0, ios::end );
    size_t length = file.tellg();
    file.seekg( 0, ios::beg );
    
    // in Buffer einlesen
    vector<char> buffer( length );
    file.read( &buffer[0], length );
    
    // und ab damit
    send( s, &buffer[0], length, 0 );
    


  • omg schrieb:

    und wie kann ich dann aus dem empfangegen buffer wieder eine datei erstellen?

    Dazu musst du natürlich vorher mitschicken, wie groß die Datei ist, also beim Senden noch send( s, &length, sizeof(length), 0 ); .
    Beim Empfangen halt erst die Länge der Datei empfangen (sizeof(length), sizeof(length) muss aber bei Empfänger und Sender gleich sein!) und dann solange empfangen, bis die Datei komplett da ist (eben bis 'length' Bytes gelesen sind).

    edit: Programmierst du eigentlich mit C oder mit C++?



  • vielen vielen dank Badestrand!! ich programmiere C++.
    Aber wenn ich jetzt die bytes empfangen habe muss ich ja auch irgendwie die Datei wieder erstellen am Empfänger also das Bild.
    Und noch ne Frage: da steht binary bei fopen.
    Gehen da trotzdem bilder?



  • omg schrieb:

    vielen vielen dank Badestrand!! ich programmiere C++.

    Das ist gut 🙂 Du könntest dir auch mal SFML anschauen, damit ist das Socket-Handling um einiges einfacher.

    omg schrieb:

    Aber wenn ich jetzt die bytes empfangen habe muss ich ja auch irgendwie die Datei wieder erstellen am Empfänger also das Bild.

    Genau, einfach mit ofstream eine schreibende Datei mit Endung ".jpg" erzeugen/öffnen und den Dateiinhalt reinschreiben. Dann kannst du sie ganz normal im Explorer öffnen.

    omg schrieb:

    Und noch ne Frage: da steht binary bei fopen.
    Gehen da trotzdem bilder?

    Ja klar, "binary" ist allumfassend, alle Daten sind binär. Textdaten oder Bilddaten sind auch binär, werden aber besonders dargestellt (eben als Text/Bild), weil sie vom Computer erst nach bestimmten Standards (siehe Dateiformat von Jpegs oder ASCII-Format) interpretiert werden.



  • ok danke
    send( s, &length, sizeof(length), 0 );
    konvertierung des 2 paramteter von size_t in char nicht möglich oO



  • Evtl. send( s, static_cast<const char*>(&length), sizeof(length), 0 ); ?



  • soweit bin ich schon:
    Server

    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
     	WSADATA wsa;
    	SOCKADDR_IN addr;
    	int rc;
    	SOCKET acceptSocket, connectedSocket;
    	if(WSAStartup(MAKEWORD(2,0), &wsa) != 0)
    	{
    		cout << "Socket konnte nicht gestartet werden" << endl;
    	}
    	acceptSocket = socket(AF_INET,SOCK_STREAM,0);
    	if(acceptSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht erstellt werden" << endl;
    	}
    	memset(&addr,0,sizeof(SOCKADDR_IN));
    	addr.sin_family=AF_INET;
    	addr.sin_port=htons(40791);
    	addr.sin_addr.s_addr=INADDR_ANY;
    	if(bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    	{
    		cout << "Socket konnte nicht gebindet werden" << endl;
    	}
    	if(listen(acceptSocket,10)==SOCKET_ERROR)
    	{
    		cout << "listen ist fehlgeschlagen" << endl;
    	}
    	connectedSocket=accept(acceptSocket,NULL,NULL);
    	if(connectedSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht akzeptiert werden" << endl;
    	}
    	size_t length;
    	recv(connectedSocket, (char *)length, sizeof(length), 0);
    	cout << length << endl;
    	system("PAUSE");
    	return 0;
    }
    

    Client:

    int main()
    {
    
    	SOCKET s;
    	WSADATA wsa;
    	SOCKADDR_IN addr;
    	int rc;
    	if(WSAStartup(MAKEWORD(2, 0), &wsa) != 0)
    	{
    		cout << "Winsock konnte nicht gestartet werden" << endl;
    	}
    	s = socket(AF_INET, SOCK_STREAM, 0);
    	if(s == INVALID_SOCKET) 
    	{
    		cout << "Socket konnte nicht erstellt werden" << endl;
    	}
    	memset(&addr, 0, sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten 
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(40791); // wir verwenden mal port 40791
    	rc = getAddrFromString(TEXT("ip"), &addr);
    	if(rc == SOCKET_ERROR)
    	{
    		cout << "IP konnte nicht aufgelöst werden" << endl;
    	}
        if(connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR)) == SOCKET_ERROR) 
    	{
    		cout << "Konnte nicht verbinden" << endl;
    	}
    	ifstream file( "tmp.jpg", ios::binary );
    	// Dateigröße ermitteln
    	file.seekg( 0, ios::end );
    	size_t length = file.tellg();
    	file.seekg( 0, ios::beg );
    	// in Buffer einlesen
    	vector<char> buffer( length );
    	file.read( &buffer[0], length );
    	// und ab damit
    	send( s, (const char*)length, sizeof(length), 0 );
    [cpp]
    

    leider gibt der Server immer 7143525 aus, egal wie groß die datei ist.
    Woran kann das liegen?



  • &



  • ahh danke



  • jedoch gibt das immer noch 2 kbs oder so dazu.
    Wenn die datei so 63 kb groß ist gibt es 65781 und so aus.
    Ist das normal?



  • Server:

    #include <windows.h>
    #include <iostream>
    #include <vector>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
     	WSADATA wsa;
    	SOCKADDR_IN addr;
    	int rc;
    	SOCKET acceptSocket, connectedSocket;
    	if(WSAStartup(MAKEWORD(2,0), &wsa) != 0)
    	{
    		cout << "Socket konnte nicht gestartet werden" << endl;
    	}
    	acceptSocket = socket(AF_INET,SOCK_STREAM,0);
    	if(acceptSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht erstellt werden" << endl;
    	}
    	memset(&addr,0,sizeof(SOCKADDR_IN));
    	addr.sin_family=AF_INET;
    	addr.sin_port=htons(40791);
    	addr.sin_addr.s_addr=INADDR_ANY;
    	if(bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    	{
    		cout << "Socket konnte nicht gebindet werden" << endl;
    	}
    	if(listen(acceptSocket,10)==SOCKET_ERROR)
    	{
    		cout << "listen ist fehlgeschlagen" << endl;
    	}
    	connectedSocket=accept(acceptSocket,NULL,NULL);
    	if(connectedSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht akzeptiert werden" << endl;
    	}
    	size_t length;
    	recv(connectedSocket, (char *)&length, sizeof(length), 0);
    	vector<char> buffer( length );
    	cout << length << endl;
    	recv(connectedSocket, &buffer[0], length, 0);
    	int i = 0;
        ofstream Zieldatei("tmp.jpg");          
        if (!Zieldatei)                             // Fehler beim Öffnen?
    		cerr << "Ausgabe-Datei kann nicht geöffnet werden\n"; 
        else {            // falls es funktioniert hat 
    		while(i != length)
            Zieldatei.put(buffer[i]);   
    		cout << "erfolgreicht" << endl;
    	}
    	system("PAUSE");
    	return 0;
    }
    

    Client ausschnitt

    ifstream file( "tmp.jpg", ios::binary );
    	// Dateigröße ermitteln
    	file.seekg( 0, ios::end );
    	size_t length = file.tellg();
    	file.seekg( 0, ios::beg );
    	// in Buffer einlesen
    	vector<char> buffer( length );
    	file.read( &buffer[0], length );
    	// und ab damit
    	cout << length << endl;
    	send( s, (const char*)&length, sizeof(length), 0 );
    	Sleep(1000);
    	send( s, &buffer[0], length, 0 );
    

    verdammt was mach ich nur falsch 😞
    manchmal gibt der server gar nicht erfolgreich aus aber der Client ist schon wieder abgeschlossen und manchmal klappt es aber bei der datei kommt immer fehler bei der vorschau zum anschaun OO



  • Das könnte daran liegen, dass recv nicht unbedingt immer alle Daten empfängt. Überprüf doch mal den Return-Wert von recv und du brauchst wohl eine Schleife, die solange empfängt, bis die Daten da sind. Oder auch 'ne Hilfsfunktion, die ungefähr so aussieht:

    bool RecvData( SOCKET s, char* data, size_t bytes )
    {
        size_t bytes_read = 0;
        while ( bytes_read != bytes )
        {
            int r = recv( s, data+bytes_read, bytes-bytes_read, 0 );
    
            // Grad keine Daten zum empfangen da?
            if ( r==-1 && WSAGetLastError()==WSAEWOULDBLOCK )
                Sleep( 20 );
            // Fehler bzw Verbindung geschlossen?
            else if ( r <= 0 )
                return false;
            else
                bytes_read += r;
        }
        return true;
    }
    

    edit: Der Code ist ungetestet. Und recv kann halt z.B. beim ersten Aufruf nur 5 Bytes empfangen, beim zweiten noch ein paar und beim dritten den Rest. Oder so, jedenfalls wartet es nicht, bis man die angegebene Anzahl an Bytes empfangen hat.



  • danke 🙂
    jetzt wird die jpg jedes mal erstellt aber sie hat zirka 15 mb und kann nicht angezeigt werden 😞

    #include <windows.h>
    #include <iostream>
    #include <vector>
    #include <fstream>
    
    using namespace std;
    
    char* RecvData( SOCKET s, size_t bytes );
    
    int main()
    {
     	WSADATA wsa;
    	SOCKADDR_IN addr;
    	int rc;
    	SOCKET acceptSocket, connectedSocket;
    	if(WSAStartup(MAKEWORD(2,0), &wsa) != 0)
    	{
    		cout << "Socket konnte nicht gestartet werden" << endl;
    	}
    	acceptSocket = socket(AF_INET,SOCK_STREAM,0);
    	if(acceptSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht erstellt werden" << endl;
    	}
    	memset(&addr,0,sizeof(SOCKADDR_IN));
    	addr.sin_family=AF_INET;
    	addr.sin_port=htons(40791);
    	addr.sin_addr.s_addr=INADDR_ANY;
    	if(bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    	{
    		cout << "Socket konnte nicht gebindet werden" << endl;
    	}
    	if(listen(acceptSocket,10)==SOCKET_ERROR)
    	{
    		cout << "listen ist fehlgeschlagen" << endl;
    	}
    	connectedSocket=accept(acceptSocket,NULL,NULL);
    	if(connectedSocket==INVALID_SOCKET)
    	{
    		cout << "Socket konnte nicht akzeptiert werden" << endl;
    	}
    	size_t length;
    	recv(connectedSocket, (char *)&length, sizeof(length), 0);
    	cout << length << endl;
    	char *buffer = RecvData(connectedSocket, length);
    	int i = 0;
        ofstream Zieldatei("tmp.jpg");          
        if (!Zieldatei)                             // Fehler beim Öffnen?
    		cerr << "Ausgabe-Datei kann nicht geöffnet werden\n"; 
        else {            // falls es funktioniert hat 
    		while(i != length)
            Zieldatei.put(buffer[i]);   
    		cout << "erfolgreicht" << endl;
    	}
    	system("PAUSE");
    	return 0;
    }
    
    char* RecvData( SOCKET s, size_t bytes )
    {
        size_t bytes_read = 0;
    	static char tempBuff[1000000];
        while ( bytes_read != bytes )
        {
            int r = recv( s, tempBuff+bytes_read, bytes-bytes_read, 0 );
    
            // Grad keine Daten zum empfangen da?
            if ( r==-1 && WSAGetLastError()==WSAEWOULDBLOCK )
                Sleep( 20 );
            // Fehler bzw Verbindung geschlossen?
            else if ( r <= 0 )
                return false;
            else
                bytes_read += r;
        }
        return tempBuff;
    }
    


  • Also das mit dem tempBuff in RecvData ist aber ein bisschen dreckig 😃 Was gibt der Server denn bei cout << length << endl; aus?



  • genau das gleiche wie der Client.
    Also immer so 2 kb mehr wie die dateigröße von jpg.



  • Also immer so 2 kb mehr wie die dateigröße von jpg.
    Es sollten aber eigentlich nur 4 Bytes mehr sein 😕

    Zieldatei.put(buffer[i]); => Zieldatei.put(buffer[i++]); ? 🙂

    Bzw

    ofstream Zieldatei( "tmp.jpg", ios::binary ); // Wichtig, das "binary" nicht vergessen!
    ...
    Zieldatei.write( buffer, length );
    


  • upsi, da hab ich wohl das ++ vergessen *schäm*
    jetzt kommen wir der sache schon verdammt nahe!
    Die datei aht ne normale größe und kann angezeigt werden.
    Aber wenn ich sie öffne erstehen solche bilder:
    http://img224.imageshack.us/my.php?image=tmpsm1.jpg
    (soll ein screen vom desktop sein)


Anmelden zum Antworten