Socketproblem: recv()
-
Hallo Leute,
habe eine Klasse netsocket geschrieben, u.a. mit der Funktion Receive. Hier habe ich folgendes beim Debuggen festgestellt. Reist die Verbindung kurz vor dem "empfangen = ::recv(..." ab, so hängt sich das Programm auf. Das heißt, der Debugger beendet diese Zeile nicht.
Wenn ich aber die Dokumentation richtig verstanden habe, so müsste doch aber die Funktion recv() eine 0 zurückliefern, wenn diese ein Problem hat, aber sich doch nicht totwarten.Wie bekomme ich das Problem gelöst?
Gibt es evtl. eine komplett fertige Socketklasse, welche fehlerresistent und frei verwendbar ist?
bool netsocket::Receive(string& s) const { char buf [MAXRECV + 1]; int empfangen; try { s = ""; memset (buf, 0, MAXRECV + 1); empfangen = ::recv(m_sock, buf, MAXRECV, 0); if (empfangen > 0 || empfangen != SOCKET_ERROR) { s = (string)buf; return true; } } catch (...) { return false; } return false; }
-
Hallo,
Benutze die Forensuche für die Suche nach einer Socket Klasse oder einer Networking Library. Es wimmelt von einträgen, wo regelemässig alle brauchbaren Libraries aufgelistet werden.Ich würde sagen, hier muss es && heissen.
if (empfangen > 0 && empfangen != SOCKET_ERROR) { //s = (string)buf; // ich würde den CTOR bevorzugen. s = string(buf); return true; }Zudem kann es sein, dass Du zuerst die hälfte des Strings empfängst und beim zweiten Aufruf von recv erst die zweite hälfte...
Wenn SOCKET_ERROR zurückgegeben wird kannst Du mir WSAGetLastError den genauen Fehler feststellen.
Wenn ich aber die Dokumentation richtig verstanden habe, so müsste doch aber die Funktion recv() eine 0 zurückliefern, wenn diese ein Problem hat, aber sich doch nicht totwarten.
Gilt nur bei Verbindungsorientierten sockets (sprich TCP/IP).
Gruss Simon
-
Hallo simon.gysi,
ich versuche eine POP3-Schnittstelle zu schreiben. Du hast selbstverständlich recht, dass recv() nicht unbedingt alle Daten empfängt (pufferabhängig), so dass ggf. mehrere recv()-Vorgänge notwendig sind. Dies habe ich schon berücksichtigt.
A-Bär: Das Problem ist jedoch, dass er unter bestimmten Bedingungen nicht bis zur Zeile
if (empfangen > 0 && empfangen != SOCKET_ERROR)vordringt, sondern schon eine Zeile vorher bei
empfangen = ::recv(m_sock, buf, MAXRECV, 0);nicht weitermacht. Das heißt, mein Debugger bekommt keine Rückmeldung - das Programm scheint bei diesem Befehl stehenzubleiben, ohne dass überhaupt eine Chance habe ggf. kurz danach mit WSAGetLastError Fehler abzufragen...
Nachtrag: Noch eine kleine Ungereimtheit habe ich bei POP3 festgestellt. Sende ich den LIST-Befehl, so erhalte ich eine Liste alle verfügbaren Mails einschließlich Grüßenangabe. Jedoch weicht diese Angabe von dem tatsächlich empfangenen Bytes um ca. 100 Byte ab. Das heißt, ich empfange 100 Byte mehr als per Auskunft über LIST. Werden bei LIST evtl. irgendwelche Steuerzeichen nicht mit berücksichtigt? Oder wie oder was?
-
Hallo zusammen
http://msdn2.microsoft.com/en-us/library/ms740121.aspx
Aus MSDN:
If no incoming data is available at the socket, the recv call blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect functions can be used to determine when more data arrives.
Somit würde ich vermuten das es versucht weiter Daten zu empfangen da aber nichts ansteht und die Verbindung aber noch aufrecht bleibt(sprich: Server beendet die Verbindung nicht was auch Sinn macht da du ja z.B. nach dem du die größe der n'ten Mail mit LIST (n) holste dies dan vielleicht runterladen willst und wennste da jedes mal wieder ne neue Verbindung aufbauen müsstest wärs ja a schmarn
) ist die Funktion einfach noch im "blocking mode".Wenn du jetzt mit Fenstern abreitest und keine Konsolenprogramm schreibst würde ich dir mir die WSAAsyncSelect http://msdn2.microsoft.com/en-us/library/ms741540.aspx Funktion empfehlen
Ich hoff ich konnte dir helfen
Mfg PinguGroup
-
das Probem ist aber, dass es eine Konsolenanwendung sein muss (Zusatztask zu einer Serveranwendung). Und genau hierfür suche ich eine Lösung.
-
Hi
dan musste halt dafür sorgen daste die recv() Funktion nur dann aufrufts wenn auch wirklich was anstehen.Zudem kann es sein, dass Du zuerst die hälfte des Strings empfängst und beim zweiten Aufruf von recv erst die zweite hälfte
Du hast selbstverständlich recht, dass recv() nicht unbedingt alle Daten empfängt (pufferabhängig), so dass ggf. mehrere recv()-Vorgänge notwendig sind.
Weiss ned obste das richtig verstanden hast hier mal ein Beispiel:
[ohne Gewähr]
du rufst recv auf und übergibst ein puffer der größe 100
des stehen 50bytes am socket an
recv liest aber nur 25 in dein buffer
somit musste recv nochmal aufrufen um den rest zu "holen"ist also nicht pufferabhängig
[/ohne Gewähr]Wenn das nicht stimmt berichtigt mich.
MFG PinguGroup
-
@PinguGroup:
ist also nicht pufferabhängig
Korrekt.