Frage zu Winsock



  • Morgen ich guck mir gerade das C Worker Tutorial zu Winsocks an aber ein Teil verstehe ich nicht:

    http://www.c-worker.ch/tuts/wstut_op.php

    Dort steht:

    Noch ein kleiner Hinweis: Wenn man mit Strings arbeitet hat man mehrere Möglichkeiten:
    - Entweder sendet man das terminierende \0 gleich mit, und so kann der andere den String gleich ausgeben
    oder die Variante die ich gewählt habe (ist etwas sicherer)
    - Man prüft zuerst den Rückgabewert von recv, ist es kein Fehler macht man folgendes:
    buf[rc]='\0';

    (Annahme: buf ist der Buffer der die Daten speichert, und rc der Rückgabewert)
    Da recv() ja die Anzahl der empfangenen Bytes zurück gibt wird so automatisch hinter dem letzten empfangenen Zeichen ein \0 angefügt.

    Wieso ist das jetzt rc der Rückgabewert von revc 😕

    rc=recv(kSock,buf,256,0);
    
    	if(rc==0)
            {
    	  cout<<"Server hat die Verbindung getrennt..\n";
    	  system("PAUSE");
    	  return 0;
    	}
    
        if(rc==SOCKET_ERROR)
        {
    	  cout<<"Fehler: recv, fehler code: "<<WSAGetLastError();
    	 system("PAUSE");
    	  return 0;
    	}
    
    	 buf[rc]='\0';   
    
    	cout<<"\nServer antwortet: \n"<<buf;
    


  • Winsock schrieb:

    Wieso ist das jetzt rc der Rückgabewert von revc 😕

    Weil in folgendem Codestück der Variable rc der Rückgabewert von recv zugewiesen wird. Wenn Dir diese Antwort nicht weiterhilft, formuliere die Frage anders.

    rc=recv(kSock,buf,256,0);
    


  • Winsock schrieb:

    - Man prüft zuerst den Rückgabewert von recv, ist es kein Fehler macht man folgendes:
    buf[rc]='\0';
    [...]
    Da recv() ja die Anzahl der empfangenen Bytes zurück gibt wird so automatisch hinter dem letzten empfangenen Zeichen ein \0 angefügt.

    Darauf würde ich definitiv nicht setzen! Wenn du etwas sendest, kann es auch in kleinen Stückchen ankommen. Sendest du z.B. den String "Hello World", kann es z.B. sein, dass dein recv nur "Hel" empfängt und halt 3 zurückgibt, von wegen 3 Bytes empfangen. Das nächste recv würde dann vielleicht den Rest empfangen, evtl aber auch nur einen einzigen weitern Buchstaben.
    Um das zu umgehen, muss der String null-terminiert sein (wie von dem Tutorial vorgeschlagen, recv in einer Schleife aufrufen, bis ein Fehler kommt oder das Zeichen '\0' dabei ist) oder du musst die Länge des String vorwegschicken (z.B. als 32-Bit Binärzahl).



  • Übrigens würde ich dir gerne eine Bibliothek an's Herz legen, die das Ganze für dich kapselt. Du könntest dir z.B. boost::asio oder SFML anschauen.

    Unter SFML sähe das dann in etwa so aus:

    // Senden
    sf::Packet packet;
    packet << "Hello World";
    socket.Send( packet );
    
    // Empfangen
    std::string received_string;
    sf::Packet packet;
    
    if ( socket.Receive(packet) != sf::Socket::Status::Done )
        ; // Fehler
    
    packet >> received_string;
    if ( ! packet )
        ; // Fehler
    
    std::cout << received_string << std::endl; // String ausgeben
    

Anmelden zum Antworten