pop und smtp Server connecten
-
Hi,
ich habe eine kleine dll geschrieben welche grundlegende Winsocket Funktionen zur verfügung stellt. Eine Funktion zum connecten (connect) eine zum senden und eine zum empfangen der Daten.
Hab das ganze mal mit meinem Webserver getestet, sprich auf Port 80 connectet und einen GET gesendet und die Seite wieder empfangen.
So nun wollte ich mit einem pop3 Server connecten, hab auch alles schön angegeben, Port 110 Server und so stimmt, der connect klappt auch ohne Fehler, nur wenn ich versuche nen Login zu machen geht gar nichts mehr.
Sprich ich sende "USER username" dann will ich die Server antwort empfangen, und schon da hängt sich die Schleife auf die die Antworten empfangen soll:
EXPORT char* CALLBACK net_receive(SOCKET s)
{
long rc;
char* buf;
char recv_buf[256];
buf = "";while((rc=recv(s,recv_buf,256,0))>0)
{
strcat(buf,recv_buf);
}return buf;
}Keine Ahnung wieso, wie gesagt nen GET Request bei webservern macht Sie Problemlos mit. Oder muss ich bei pop Servern etwas anderes senden als "USER username"? Mit Telnet geht das auch Problemlos, dann würde noch "PASS passwd" kommen und mit "LIST" müsste die Liste der Mails zurückkommen. Aber das will alles mit meinen C Funktionen nicht so ganz funktionieren. Hoffe es kennt sich jemand damit aus?
Gruß,
ueps
-
Böser Fehler:
Du hast keinen Speicher für buf reserviert!
-
könnte mir vorstellen, dass du vom senden und empfangen her nicht die richtige reihenfolge einhältst. lies doch mal die POP (und SMTP) RFC, da steht das genau drin, wer was wann sendet.
-
Hi ihr zwei,
zum Thema Speicher reservieren, bin leider etwas neu im Gebiet C++. Wie und Wieso muss ich hier Speicher reservieren? Die länge ist doch variabel und es wird solange gelesen bis keine Daten mehr empfangen werden.
Zum Thema RFC, hab ich mir auch schon angeguckt, und einen Artikel zum Thema gelesen, da stand eine schöne Beschreibung drin wie man per Telnet auf nen pop3 Server connectet, genau das hab ich 1 zu 1 versucht, leider ohne Erfolg, evtl.liegts an fehlenden \r\n oder so am Ende des requests, ich werds nochmal lesen.
Gruß,
ueps
-
Wie und Wieso muss ich hier Speicher reservieren?
für solche Dinge schaust du am besten in dein C oder C++ Buch, was du zum lernen benutzt
ich geh mal davon aus, dass du weisst was Pointer sind (du benutzt ja auch welche
), wenn du folgenden Code hast
char *foo;
hast du einen unintialisierten Pointer der zeigt irgend wohin in den Speicher, wenn du nun versuchst ihn zu dereferenzieren, dann hast du auf einmal ein Problem. Also müssen wir den Pointer auf was zeigen lassen, damit wir ihn wirklich nutzen können. Du machst nun folgendes
char *foo="";
nun zeigt foo auf den konstanten String "" irgend wo im Speicher ("" ist ja gleich 0 vom Wert, also wurde 1 byte Speicher reserviert vom Compiler). Du willst nun irgend was dazu hinzufügen, mit strcat, da aber nun nur 1 byte Speicher reserviert ist und strcat mehr Speicher versucht zu benutzen, hast du ein Problem.
Was machen wir nun? Wir wollen uns Speicher reservieren, wo strcat genug Platz hat die anderen Strings anzufügen.
Wie das geht erfährst du hier http://www.schornboeck.net/ckurs/alloc.htm
hoffe, du hast nun das "Wie" und "Wieso" verstanden
-
Hi !
Ohne die Details deiner Socketlibrary zu kennen.. versuchs mal so:
ueps schrieb:
[...]
EXPORT char* CALLBACK net_receive(SOCKET s)
{
long rc;
char recv_buf[1024];bytes = recv(s, recv_buffer, sizeof(buffer)-1, 0);
// recv returned -1 bei fehler
if (bytes>0)
buffer[bytes] = '\0'; // ende des strings markierenreturn *recv_buf;
}
[...]
-
Hier findest du die RFC zu POP. Laut Abschnitt 3 sieht das Verbindungsschema so aus:
Server: [wartet auf Verbindungen] Client -- verbindet sich zum --> Server Server -> Client: Hallo (Greeting) Client -> Server: Befehle
du musst also gleich nach dem connect ein receive machen, sonst wird das nix
-
Hi, danke euch erstmal.
Ich habe inzwischen was vom Server zurückbekommen, ein fröhliches:
x
+OK QPOP (version 3.1) at server.blablabla starting.
Allerdings hab ich jetzt meine net_receive Methode nicht mehr als while Schleife sondern nen einzelnen Aufruf von recv(...). Warum hat er dass als Schleife nicht auch gemacht? Wenn keine Bytes mehr gelesen werden können müsste doch die Schleife beendet werden, gab allerdings immer ne Endlos Schleife? Jedenfalls würd ich halt gern alle Bytes in einem Rutsch lesen und komplett zurückgeben, das obige Beispiel ist ja auf 1024 Bytes beschränkt?
Hab gerade herausgefunden dass beim zweiten Schleifen durchlauf die Schleife beim rc=recv(s,recv_buf,256,0); hängen bleibt? Warum dass denn? Bei einem HTTP Request kommt 0 zurück wenn nix anliegt, bei pop hängt sich alles auf oder wie?
Gruß,
ueps
-
Hi !
Das Defaultverhalten der Sockets ist, dass sie im "blockingmodus" arbeiten. Das heißt, dass recv halt solange wartet bis endlich mal ein paar Bytes über die Leitung tröpfeln. Aber keine Angst, nach 3 Minuten läuft ein interner Timeout ab, und die Funktion beendet sich (toll, oder?)
Wenn dir dieser Wert zu lang ist, musst du selbst dafür sorgen dass recv zurückkehrt (oder erst gar nicht aufgerufen wird) wenn keine Daten kommen.
Unter Linux kannst du das mit der der Funktion alarm oder select machen.
In Windows geht das natürlich nicht, evtl. wäre da die Beste Lösung recv eine Callback Funktion aufrufen zu lassen wenn Daten kommen (siehe MFC C(Async)Socket)
-
Hi,
also dass mit den 3 min ist ja wohl ... Ich frage mich bloß warum beim GET Request an einen Webserver mit receive 0 zurück kommt wenn nix mehr anliegt und bei einem pop Server nicht, ist irgendwie blöd. Wie hast du dass mit der CALLBACK Funktion gemeint? Hab das irgendwie nicht ganz verstanden. Ich muss ja fast ne Schleife mit recv() durchlaufen sonst kann ich ja nie Mails > 255 anzeigen lassen?
Gruß,
ueps
-
ueps schrieb:
Hi,
also dass mit den 3 min ist ja wohl ... Ich frage mich bloß warum beim GET Request an einen Webserver mit receive 0 zurück kommt wenn nix mehr anliegt und bei einem pop Server nicht [...]Das liegt wohl daran, dass der Webserver die Verbindung sofort wieder schließt nachdem er dir Daten geschickt hat. Mach doch einfach mal einen Feldversuch mit telnet webserver 80
ueps schrieb:
[...]
Wie hast du dass mit der CALLBACK Funktion gemeint? Hab das irgendwie nicht ganz verstanden.
[...]Wie ichs gesagt habe, wenn Daten ankommen ruft deine Socketlib automatisch eine Userdefined Funktion auf...
ueps schrieb:
[...]
Ich muss ja fast ne Schleife mit recv() durchlaufen sonst kann ich ja nie Mails > 255 anzeigen lassen?Du könntest natürlich auch den Empangsbuffer vergrößern, wenn ich mich recht erinnere konnte ich mit den MFC Socketklassen maximal ~38KB auf einmal verschicken.
Aber wenn ich mich nicht täusche, wird recv mehrmals aufgerufen wenn du nicht alle Daten auf einmal holst (Angabe ohne Gewähr)
-
RFC1939:
Responses may be up to 512 characters
long, including the terminating CRLF.
-
Also mehr wie 256 Byte auf einmal sollte man nicht mit recv lesen.
Ich hab eben was von einem Paramter O_NONBLOCK gelesen, wenn der beim socket file decriptor gesetzt ist wird nicht 3 min gewartet. Allerdings hab ich nicht gefunden wie man den Wert setzt?Hab eben mal was getestet und musste feststellen dass sich alles sehr sehr merkwürdig verhält, hier der Testcode:
EXPORT int CALLBACK pop_connect(char* ip, int port, char* user, char* passwd)
{long rc;
char result[256];
char buf[256];
char buf2[256];rc=startWinsock();
mail_s = net_connect(ip, port);rc=recv(mail_s,result,256,0);
printf("%s\n",result);sprintf(buf,"USER %s\r\n", user);
printf("send: %s\n", buf);
rc=net_send(mail_s, buf);//Kritische Stelle
rc=recv(mail_s,buf2,256,0);
printf("%s\n",buf2);sprintf(buf,"PASS %s\r\n", passwd);
printf("send: %s\n", buf);
rc=net_send(mail_s, buf);rc=recv(mail_s,result,256,0);
printf("%s\n",result);strcpy(buf,"LIST\r\n");
rc=net_send(mail_s, buf);rc=recv(mail_s,result,256,0);
printf("%s\n",result);return 1;
}Die Kritische Stelle habe ich kommentiert, steht dort anstatt buf2 result, geht die Passwort abfrage nicht?!? Gott weiß warum, result und buf haben rein gar nichts miteinander zu tun?!?!?
Hier mal die Konsolen ausgabe:
+OK QPOP (version 3.1) at t28.server starting.
send: USER ueps
|í║
send: PASS poppasswd+OK selb has 0 visible messages (0 hidden) in 0 octets.
rting.+OK 0 visible messages (0 octets)
hidden) in 0 octets.
rting.Das kryptische |í║ sollte Passwort required heißen, wie gesagt lass ich statt buf2 result stehen, steht das kryptische statt PASS poppasswd.
Keine Ahnung was da wieder abgeht.
-
Ich glaube ich weiß was dein Fehler ist, bei send und recv musst du als 3 Parameter nicht die größe des Arrays übergeben, sondern die Größe - 1... also jeweils 255.
Außerdem wäre es toll wenn du die Strings noch mit \0 terminieren würdest, sonst weißt du nachher nicht wo das Ende des Strings ist, kein sehr praktischer Zustand.Also müsste deine kritische Stelle in etwa so aussehen:
rc=recv(mail_s,buf2,255,0); if (rc>0) buf2[rc] = '\0'; printf("%s\n",buf2);
Ich hoffe das wars
-
Jepp, dass mit dem \0 Terminieren vergess ich immer, nen char[5] kann man dann theoretisch ja nur einen 4 stelligen String haben weil ja noch \0 dazu kommt, was bei mir immer wieder zu Fehlern führt
Ich bin halt noch die easy Deklaration von VB , PHP und Cop gewohnt
Das mit der Länge bei recv dürfte eigentlich egal sein, da ja bis max. 512 Zeichen versendet werden dürfen laut RFC. Warum muss ich 1 Byte von der Länge abziehen?
Gruß,
ueps
-
ueps schrieb:
[...]
Warum muss ich 1 Byte von der Länge abziehen?Weil du doch noch den \0 setzen musst...