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