[Einsteiger] Socket für mehrere Anfragen nutzen?
-
Hallo,
ich arbeite mich zur zeit langsam in C hinein und beschäftige mich jetzt mit Sockets. Aus diversen Tutorials habe ich mir ein kleines Programm geschustert, das testweise verschiedene Dateien via HTTP aus dem Netz laden soll.
Bisher habe ich festgestellt:
Wenn ich nach jeder Datei den Socket freigebe ( close(sock_id); ) und für eine neue Übertragung einen neuen Socket hole, dann läuft alles ganz normal.Allerdings dachte ich mir, ich könnte mit dem Socket so viel machen wie ich will, bevor ich ihn schließe. Wenn ich aber die 2., 3. und alle weiteren Anfrage sende, dann bekomme ich jedes mal 0 Bytes zurück.
Den Socket hole ich mit
int sock_id = socket(AF_INET, SOCK_STREAM, 0);
Kann mir jemand sagen, wo ich was übersehen hab?
-
Du musst den HTTP-Header analysieren. AFAIK musst du eine neue Verbindung aufbauen, wenn dort steht Connection: closed. Das könnte ein Grund für dein Problem sein. Ansonsten zeig halt mal dein Code.
blan
-
Hier mein Hauptprogramm:
int main() { char buf[65536]; char * ip = get_ip("xyz.de"); char * get = build_get_query(); // Gibt jedes Mal eine Anfrage nach einer anderen Datei zurück struct sockaddr_in * remote = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in *)); remote->sin_family = AF_INET; remote->sin_port = htons(80); int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr))); if( tmpres < 0) { printf("Can't set remote->sin_addr.s_addr\n"); exit(1); } else if(tmpres == 0) { printf("%s is not a valid IP address\n", ip); exit(1); } int i, x, sock_id; /**********************************************************************/ // "Bereich 1" sock_id = socket(AF_INET, SOCK_STREAM, 0); if(sock_id < 0) { printf("Got no Socket\n"); exit(1); } if(connect(sock_id, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){ printf("Could not connect\n"); exit(1); } /**********************************************************************/ // "Bereich 2" for(x=0;x<6;x++) { for(i=0;i<65536; buf[i++]=0x00); get = build_get_query(); // Gibt jedes Mal eine Anfrage nach einer anderen Datei zurück printf("DEBUG: get: \n%s\n\n", get); int sent = 0; while(sent < strlen(get)) { tmpres = send(sock_id, get+sent, strlen(get)-sent, 0); if(tmpres == -1){ printf("Can't send query\n"); exit(1); } sent += tmpres; } printf("DEBUG: sent: finished\n\n"); for(i=0;(tmpres = recv(sock_id, &buf[i], BUFSIZ, 0)) > 0; i+=tmpres); printf("DEBUG: recv: \n%s\n\n", buf); } /**********************************************************************/ // "Bereich 3" close(sock_id); sock_id = -1; /**********************************************************************/ free(get); free(remote); free(ip); return 0; }
Ich habe 3 Bereiche mit Kommentaren ausgezeichnet:
Wenn man Bereich 1 und 3 in Bereich 2 hineinzieht (also in die for-Schleife), dann bekomme ich alle Dateien. Wenn die Bereiche 1 und 3 allerdings, so wie jetzt, außerhalb der Schleife sind, dann arbeite ich ja ganze Zeit mit ein und dem selben Socket.Ergebnis:
Bei der ersten Anfrage bekomme ich beim recv:DEBUG: sent: finished DEBUG: recv: HTTP/1.1 200 OK Date: Sun, 31 May 2009 12:46:18 GMT Server: Apache/1.3.34 (Unix) mod_fastcgi/2.4.2 PHP/4.4.6 with Suhosin-Patch X-Powered-By: PHP/4.4.6 Content-Length: 43 Set-Cookie: CounterSession=NzE3OTIy; expires=Sun, 31 May 2009 13:06:18 GMT; path=/zwischenweltenjournal; domain=.myblog.de Connection: close Content-Type: image/gif GIF89a
Das sollte ja alles ok sein, außer vielleicht, dass ich diesen CounterSession-Cookie nicht unbedingt noch laden will...
Die folgenden Anfragen sind alle ok, aber der buffer bleibt leer (ich bekomme 0 Bytes):
DEBUG: sent: finished DEBUG: recv:
Das Connection: closed steht da wirklich.
Gibt es eine Funktion, mit der man eine Connection schließt, ohne den Socket zu verwerfen? Wenn ich einfach nochmal connect(); aufrufe gibt's nen Fehler (Bei mir: "Could not connect").
-
Also du wirst wohl eine neue Verbindung aufbauen müssen - das sollte auch kein Problem sein. Evtl. kannst du dem Server auch per HTTP mitteilen, dass du die Verbindung aufrechterhalten willst. Das könnte mit Connection: Keep-Alive gehen - bin mir jetzt aber auch nicht ganz sicher.
Den Code konnte ich mir jetzt noch nicht genau anschaun.
blan
-
Das ist die Art und Weise wie ein HTTP Web Server arbeitet, hat also nicht direkt mit Deinem Client zu tun.