Winsock recv() send() Probleme
-
Guten Tag C-Programmierer

Ich und ein Kollege haben gerade in C Snake programmiert, was wunderbar funktioniert!
Jetzt hatten wir die Idee zu zweit über LAN zu spielen... (für euch vielleicht Sinnlos ;-)), das heisst also jeder Spieler muss eine Schlange steuern, so weit so gut. Haben wir auch alles implementiert. Winsock und alles dazugehörige erstellt, läuft soweit perfekt.
Nun haben wir das Problem mit recv() und send(), da der Server (Spieler 1) und der Client (Spieler 2) gleichzeitig senden und empfangen bleiben beide Schlangen stehen. Wenn wir bei einem das Empfangen (recv) auskommentieren sieht der andere die Schlange "fahren" (seine eigene Fährt aber nicht?). Wir haben schon einiges mit select() und anderes probiert, doch dies wollte nicht funktionieren...
Habt ihr vielleicht eine Idee?
Edit: Es handelt sich um Windows Sockets
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Nutzt Asynchrone (Overlapped) Socketkommunikation o. Threads.
-
Danke für Deine Antwort ;-), nur wie "aktiviere" ich Asynchrone Socketkommunikation/Threads?
-
ich würde hier einfach non-blocking sockets verwenden
einfach mit ioctlsocket() die "FIONBIO" option entsprechend setzen
http://msdn.microsoft.com/en-us/library/ms738573(v=VS.85).aspxund natürlich müsst ihr den restlichen code entsprechend anpassen, da send() und recv() dann mit WSAGetLastError() == WSAEWOULDBLOCK zurückkommen könnten, was dann soviel bedeutet wie "nix zu empfangen" bzw. "sendepuffer sind schon randvoll"
-
Danke für Deine Antwort ;-).
Non-Blocking haben wir auch schon versucht, das Problem war aber, dass beim Verbinden ein "Das Programm Sanke.exe hat ein Problem festgestellt und musste beendet werden"-Fehler beim Client und Server kam...
-
na dann müsst ihr den bug halt fixen
alles andere is eher noch schwieriger als non-blocking, also wenn ihr das schon nicht hinbekommen habt...

-
Also meinst Du, der Fehler kommt, weil etwas falsch programmiert wurde? Ohne das non-blocking funktionierts ja tadelos, nur das halt nichts fährt ;-)...
-
Completion Ports
-
cal schrieb:
Also meinst Du, der Fehler kommt, weil etwas falsch programmiert wurde? Ohne das non-blocking funktionierts ja tadelos, nur das halt nichts fährt ;-)...
Ja, "... hat ein Problem festgestellt und musste beendet werden" heisst nichts anderes, als das dein Programm (z.B. wegen in speicher rumschreiben, wo es das nicht sollte) abgestürzt ist.
Benutzt du gar keinen Debugger?
-
Doch sicher, hier der genaue Fehler
Run-Time Check Failure #3 - The variable 'sock' is being used without being initialized.
Run-Time Check Failure #3 - The variable 'connectedSocket' is being used without being initialized.
Edit: Ok blöd, ioctlsocket() war am falschen Ort ;-)... ich versuch smal und gebe dann bescheid!
Edit2: Also es sieht alles schonmal viel besser aus! Keine Fehlermeldungen mehr ect... --> Problem ist jetzt nur noch das ich beim Client und Server bei den recv() den Wert 0 gesendet bekomme
-
Was bitte verstehst du unter "den Wert 0 gesendet bekommen"?
Bitte schreib doch einfach das was Sache ist, und nicht irgendeine vermeindlich vereinfachende Formulierung (die dann keiner versteht).
Gibt recv() 0 zurück?
Gibt recv() einen Wert > 0 zurück, und im Empfangspuffer steht dann ein Null-Byte?
...?Und bitte lies dir die Doku zu send() und recv() sehr genau durch.
Und verstehe dass ein TCP Socket ein *Stream* ist und *nicht* Message-Orientiert!
recv() empfängt keine Messages, recv() empfängt einfach mehr oder weniger Bytes. Maximal so viel wie du als Puffergrösse angibst, mindestens 1 (wenn kein Fehler gemeldet wird), alles dazwischen ist auch möglich, und hängt *nicht* damit zusammen wieviel Bytes mit send() auf einmal weggeschickt wurden.
-
Das es klarer ist:
Der Client sendet z.B. das hier:
X = 20 Y = 0itoa(X, rx, 10); itoa(Y, ry, 10); itoa(75, rr, 10); send(sock, rx, 2, 0); send(sock, ry, 2, 0); send(sock, rr, 2, 0);und der Server empfängts so:
rc = recv(connectedSocket, rx, 2, 0); rc = recv(connectedSocket, ry, 2, 0); rc = recv(connectedSocket, rr, 2, 0); int rxInt = atoi(rx); int ryInt = atoi(ry); int rrInt = atoi(rr); richtung = rrInt; fahren2(rxInt, ryInt);recv() gibt 0 zurück
-
Ich zitiere nochmal hustbaer:
hustbaer schrieb:
Und verstehe dass ein TCP Socket ein *Stream* ist und *nicht* Message-Orientiert!
recv() empfängt keine Messages, recv() empfängt einfach mehr oder weniger Bytes. Maximal so viel wie du als Puffergrösse angibst, mindestens 1 (wenn kein Fehler gemeldet wird), alles dazwischen ist auch möglich, und hängt *nicht* damit zusammen wieviel Bytes mit send() auf einmal weggeschickt wurden.Du kannst (bei TCP) quasi nicht davon ausgehen dass mit 1x recv() schon alles angekommen bist, du musst recv() ggf. mehrfach aufrufen.
Warum 2 bei send/recv?
Du wertest rc gar nicht aus?
-
Und warum überhaupt atoi/itoa?
Wenn du "brav" sein willst nimm htonl/htons vor dem Senden und ntohl/ntohs nach dem Empfangen.
Wenn du auf die Byte-Order scheisst lass das auch noch weg, und sende einfach die Bytes der int/short/...
p.S.:
geeky schrieb:
Du kannst (bei TCP) quasi nicht davon ausgehen dass mit 1x recv() schon alles angekommen bist, du musst recv() ggf. mehrfach aufrufen.
Nur als Ergänzung: es kann auch umgekehrt sein, recv() kann auch Daten empfangen die mit mehreren send() gesendet wurden.
Kurz: ausser dass die Reihenfolge erhalten bleibt, und auch keine "Löcher" im Datenstrom entstehen, kann man sich auf nix verlassen.
-
Also wenn ich das richtig verstanden habe benutzt du jetzt grade nicht-blockierende Sockets?
Dann würde ich einfach mal die gehauptung aufstellen, dass du "0" empfängst, weil du zu dem Zeitpunkt, in dem recv() aufgerufen hast noch keine Daten vorliegen.
Du müsstes also mit select() arbeiten.
Und noch den Tpp von hustbaer kurz erklärt: er meint, dass du nicht nur char per send/recv verschicken/empfangen kannst.int i = 8; send(sock,&i,sizeof(int),0);int i; recv(sock,&i,sizeof(int),0);funktioniert genauso. Solange du das mit deinen eigenen Programmen machst ist es egal wie/was du sendest - solange du auf beiden Seiten das gleiche machst!