TCP Server; Socket; Dateien senden



  • Ich hab mir einen kleinen TCP Server geschrieben, der kann bisher mit send und receiv texte hin und her schicken. Soweit ganz gut, aber was muss ich machen, damit ich dateien senden und verschicken kann?



  • Dasselbe, nur mit dem Inhalt der Dateien statt der Texte.



  • ok, aber wie viel Bit bzw. Byte kann man denn gleichzeitig schicken?oder muss
    man das nicht beachten?



  • Soviele, wie dein Socket verkraftet (afaik melden send() und recv() zurück, wieviele Daten sie verschickt/empfangen haben - wenn das nicht alle übergebenen Daten waren, mußt du den Rest evt. nochmal senden).



  • [EDIT] Geändert wegen einsicht

    mach dir eine schleife

    FILE* f;
    int sent = 0;
    int tosend = filesize;
    int sendpacksize;
    while(sent < tosend) {
        sendpacksize = tosend - sent;
        int sucessfullsent = send(Socket, f, sendpacksize);
        sent += successfullsent;
        f += successfullsent;
    }
    

    beim empfang kannst du dasselbe machen
    ALLERDINGS
    solltest du bevor du sendest noch einen int-wert mit der gesamtlänge schicken damit du auf empfängerseite weist WANN die übertragung komplett ist.

    also praktisch send(gesamtlänge) -> sendschleife(datei).
    und beim empfänger recv(länge) -> recv(datei) bis komplett.

    es werden dir noch tausend andere eventualitäten auffallen wenn du damit arbeitest aber das würde die maximale zeichenlänge für einen post glaub ich sprengen



  • Das mit SO_MAX_MSG_SIZE ist quatsch.



  • sagt wer ? .... schreib dein namen dazu wenn du den mumm aufbringen kannst -.-
    und schreib am besten gleich noch wofür das dann bitte da iss, lass mich in der beziehung gern belehren aber nich mit so nem dämlich satz wie

    ...das iss quatsch ...

    [EDIT] hab grad nachgesehen, hast zwar recht mit deiner aussage (biezieht sich nur auf DGRAM sockets) aber deine art ist sehr unhöflich -.-



  • C++ kennt kein getsockopt, vom Fragesteller wurde auch kein spezielles OS oder Framework genannt.

    Wohin gehört also das getsocktopt von Dir ?



  • @Knuddlbaer:
    <klugscheiss>Standard-C++ kennt auch kein send und receiv, also hätte keine dieser Antworten je gegeben werden dürfen.</klugscheiss>

    getsockopt ist genau wie send und recv Bestandteil von BSD-Sockets und sowohl unter UNIX (Linux) wie auch unter Windows bekannt.



  • Ceos schrieb:

    [EDIT] Geändert wegen einsicht

    mach dir eine schleife

    FILE* f;
    int sent = 0;
    int tosend = filesize;
    int sendpacksize;
    while(sent < tosend) {
        sendpacksize = tosend - sent;
        int sucessfullsent = send(Socket, f, sendpacksize);
        sent += successfullsent;
        f += successfullsent;
    }
    

    beim empfang kannst du dasselbe machen
    ALLERDINGS
    solltest du bevor du sendest noch einen int-wert mit der gesamtlänge schicken damit du auf empfängerseite weist WANN die übertragung komplett ist.

    also praktisch send(gesamtlänge) -> sendschleife(datei).
    und beim empfänger recv(länge) -> recv(datei) bis komplett.

    es werden dir noch tausend andere eventualitäten auffallen wenn du damit arbeitest aber das würde die maximale zeichenlänge für einen post glaub ich sprengen

    danke für die antwort, aber ich find keine version von send die den typ FILE akzeptiert, send akzeptiert nur char.......muss ich mir die ganze datei jetzt einlesen und als textstring senden?



  • *push*, problem besteht immernoch 🙂



  • puilina schrieb:

    danke für die antwort, aber ich find keine version von send die den typ FILE akzeptiert, send akzeptiert nur char.......muss ich mir die ganze datei jetzt einlesen und als textstring senden?

    Kurz: Ja, das mußt du (alternativ kannst du die Datei auch stückchenweise lesen und versenden).



  • kann man den FILE* nich einfach (char*) casten ?
    nur ne theorie, kanns grad nicht testen



  • Klar kannst du es casten, aber damit wirst du kaum etwas sinnvolles anstellen können. FILE ist eine Struktur, über die die <cstdio>-Funktionen auf eine BS-Datei zurückgreifen können - wenn du den FILE* in einen char* umwandelst, kannst du höchstens die Kontrollinformationen zu der Datei lesen (und mit etwas Geschick erraten, was sie darstellen sollen) - aber auf diesem Weg kommst du nicht an den Inhalt der Datei ran.



  • Also das senden scheint zu funktionieren, aber beim Empfangen verhält sich mein programm irgendwie "nicht den erwartungen entsprechend".

    Ich schicke mir zum Test eine datei die 2000 Byte groß ist, wenn ich mit dem Debugger drauf gehe erhalte ich etwa ~1400 Byte und plötzlich springt der Debugger aus der Routine raus ins Nirvana.

    Irgendwas scheitn da einen abbruch auszulösen. Der Debugger macht aber nirgendenwo weiter. Das programm befindet sich noch im debugmodus, aber nichts passiert mehr.

    Er verlässt die schleife mittendrin, wenn etwa 2/3 aller byte gelesen wurden(sind in meinem testfall derzeit immer ~2000). Laut Debugger ereicht mein Programm nie die Return anweisung, kompilieren lässt sich aber alles fehlerfrei.

    Die Datei dich mir sende lese ich mir mit fstream ein und schicke diese dann los, könnte es evtl. daran liegen das irgendwann ein zeichen kommt(z.b. carriege return) das den debugger so aus der bahn haut?

    Hier mal meine Receiv-Funktion

    std::string CCreateSocket::ReceivData(SOCKET recvSocket)
    {
    	int iLenReceived = 0;
    	std::string	tempString;
    
    	while(iLenReceived +=recv(recvSocket, this->buf, 256, 0))
    	{
    		std::cout<<WSAGetLastError();
    		tempString = tempString + std::string(this->buf);
    		/* Wegen dem Empfangen gucken, läuft im Loop, ohne Ende */
    	}
    
    	return tempString;	
    }
    

    Sieht jemand woran es liegen könnte?



  • *push*



  • Für die Abbruchbedingung mußt du den Rückgabewert von recv() direkt überprüfen - nicht die Summe aller bisher empfangenen Daten.

    PS: "Reciev" schreibt man übrigens mit IE 😃 - edit: Oder auch nicht - also vergiss den letzten Satz wieder 🙄



  • mal abgesehen das du den wert der emfangenen daten mit nichts vergleichst (dateiende z.B.)

    puilina schrieb:

    Irgendwas scheitn da einen abbruch auszulösen.

    Wenn der Dateinhalt nicht reiner text ist kann es passieren das du bei tempstring nicht alles lesen kannst, wenn dort irgendwo eine 0 steht (also binär 0) kann es sein das jeder weitere inhalt von tempstring ignoriert wird.

    ... könnte es evtl. daran liegen das irgendwann ein zeichen kommt(z.b. carriege return) das den debugger so aus der bahn haut?

    vielleicht nicht carriage return aber gut möglich das du wegen irgendeinem sonderzeichen hängen bleibst.

    Hier mal meine Receiv-Funktion

    std::string CCreateSocket::ReceivData(SOCKET recvSocket)
    {
    	int iLenReceived = 0;
    	std::string	tempString;
            int iFileEnd;
            int res = recv(recvSocket, iFileEnd, sizeof(int), 0); // Dateilänge empfangen
                                                   //muss auf serverseite natürlich vorher gesendet werden
            if (res = 0) {
                cout<<WSAGetLastError();
                return "";
            }
    
    	while(iLenReceived < iFileEnd) // Auf vollständigkeit prüfen
    	{
    		res = recv(recvSocket, this->buf, 256, 0);  // Empfangen
                    if (res = 0) {    // Auf Fehler prüfen
                       cout<<WSAGetLastError();
                       return tempString;
                    }
                    iLenReceived += res;   // Empfang aufsummieren
    		tempString = tempString + std::string(this->buf); // das geht nur mit reinen textdateien gut
    	}
    
    	return tempString;	
    }
    

    PS @ CStoll will ja nicht rechthaberisch wirken (obwohl es mir jemand unbedingt unterstellen wollte) aber
    http://dict.leo.org/ende?lp=ende&p=/gQPU.&search=receive



  • Ceos schrieb:

    PS @ CStoll will ja nicht rechthaberisch wirken (obwohl es mir jemand unbedingt unterstellen wollte) aber
    http://dict.leo.org/ende?lp=ende&p=/gQPU.&search=receive

    OK, du hast mich überzeugt 🙄


Anmelden zum Antworten