Http & Socket Problem...
-
Hey Leute

bin recht neu in der c++ Welt (ne knappe woche aktiv), naja die grundlagen kann ich aber eigentlich (oop und klassen & syntax etc)
wollte mich ma an die netztwerk programmierung ranmachen und hab mir gedacht ich mach das einefach mal in verbindung mit http
nun habe ich die folgende klasse...#include <iostream> #include "Http.h" #include <windows.h> #include <winsock2.h> #include <stdio.h> #include <sstream> #include <cstring> #include <string> #include <fstream> using namespace std; Http::Http()//Constructor { Port = 80; SendPacket(FormPacket("www.google.de")); } Http::~Http()//Destructor { //dtor } string Http::SendPacket(string Packet) { WSADATA wsa; long rc = WSAStartup(MAKEWORD(2,2),&wsa); if(rc != 0) cout << "Fehler beim starten von WSA. Fehler: " << rc << endl; else cout << "WSA erfolgreich gestartet" << endl; SOCKET sock; sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(sock == INVALID_SOCKET) cout << "Fehler beim erstellen des Sockets. Fehler: " << WSAGetLastError() << endl; else cout << "Socket erfolgreich erstellt" << endl; SOCKADDR_IN addr; memset(&addr,0,sizeof(SOCKADDR_IN)); // zuerst alles auf 0 setzten addr.sin_family=AF_INET; addr.sin_port=htons(Port); //Port setzen rc = HostAufLoesen(const_cast<char *>(Host.c_str()),&addr); if(rc == SOCKET_ERROR) cout << "Ip konnte nicht aufgeloest werden" << endl; else cout << "Ip erfolgreich aufgeloest" << endl; rc=connect(sock,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(rc==SOCKET_ERROR) cout << "Fehler beim verbinden. Fehler: " << WSAGetLastError() << endl; else cout << "Verbindung mit " << Host << " wurde erfolgreich aufgebaut" << endl; SendAll(sock,Packet.c_str(),Packet.length()); stringstream out; out << Packet.length(); cout << "LAENGE!!:::" << out.str(); // if(rc == SOCKET_ERROR) // cout << "Fehler beim senden des Packetes. Fehler: " << WSAGetLastError() << endl; // else // cout << "Packet erfolgreich gesendet" << endl; char buf2[123456]; rc = recv(sock, buf2,123456,0); if(rc == SOCKET_ERROR) cout << "Fehler beim empfangen der Antwort. Fehler: " << WSAGetLastError() << endl; else cout << "Antwort erfolgreich empfangen:" << endl; closesocket(sock); WSACleanup(); cout << buf2 << endl; ofstream myfile; myfile.open ("example.html"); if(!myfile.is_open()) cout << "\nFail!!!!!\n" << endl; myfile << Packet; myfile.close(); cout << "PENIS!"; return ""; } void Http::SendAll(int socket, const char* const buf, const int size) { int bytesSent = 0; // Anzahl Bytes die wir bereits vom Buffer gesendet haben do { bytesSent += send(socket, buf + bytesSent, size - bytesSent, 0); } while(bytesSent < size); } long Http::HostAufLoesen(char* hostnameOrIp, SOCKADDR_IN* addr) { long rc; unsigned long ip; HOSTENT* he; /* Parameter prüfen */ if(hostnameOrIp==NULL || addr==NULL) return SOCKET_ERROR; /* eine IP in hostnameOrIp ? */ ip=inet_addr(hostnameOrIp); /* bei einem fehler liefert inet_addr den Rückgabewert INADDR_NONE */ if(ip!=INADDR_NONE) { addr->sin_addr.s_addr=ip; return 0; } else { /* Hostname in hostnameOrIp auflösen */ he=gethostbyname(hostnameOrIp); if(he==NULL) { return SOCKET_ERROR; } else { /*die 4 Bytes der IP von he nach addr kopieren */ memcpy(&(addr->sin_addr),he->h_addr_list[0],4); } return 0; } } string Http::FormPacket(string sUrl, string sPost, string sType) //Create the Packetstring { if(sPost == "") PacketToSend += "GET " + GetSubPage(sUrl) +" HTTP 1.1\r\n"; else PacketToSend += "POST " + GetSubPage(sUrl) +" HTTP 1.1\r\n"; PacketToSend += "Host: " + GetSubHost(sUrl) + "\r\n"; if(UserAgent == "") PacketToSend += "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729)\r\n"; else PacketToSend += "User-Agent: " + UserAgent + "\r\n"; PacketToSend += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; PacketToSend += "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3\r\n"; PacketToSend += "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"; PacketToSend += "Keep-Alive: 115\r\n"; PacketToSend += "Connection: keep-alive\r\n"; if(Cookies != "") PacketToSend += "Cookie: " + Cookies + "\r\n"; if(Referer != "") PacketToSend += "Referer: " + Referer + "\r\n"; if(sPost != "") { PacketToSend += "Content-Type: " + sType + "\r\n"; PacketToSend += "Content-Length: "; stringstream out; out << sPost.length(); PacketToSend.append(out.str()); PacketToSend += "\r\n\r\n"; PacketToSend += sPost; } else { PacketToSend += "\r\n"; } cout << "Packet:\r\n\r\n" << PacketToSend << endl; return PacketToSend; } string Http::GetSubPage(string sUrl) // Example: 'http://google.de/index.php' -> '/index.php' { string tUrl; string Page; if(sUrl[0] == 'h' && sUrl[1] == 't' && sUrl[2] == 't' && sUrl[3] == 'p' && sUrl[4] == ':' && sUrl[5] == '/' && sUrl[6] == '/') // Check if starts with 'http://' { for(unsigned int c = 7; c < sUrl.size(); c++) { tUrl += sUrl[c]; } } else { tUrl = sUrl; } for(unsigned int c = 0; c < tUrl.size(); c++) { if(tUrl[c] == '/') { for(unsigned int c2 = c; c2 < tUrl.size(); c2++) { Page += tUrl[c2]; } break; } } if(Page == "") Page += "/"; return Page; } string Http::GetSubHost(string sUrl) // Example: 'http://google.de/index.php' -> 'google.de' { string tUrl; string bUrl; string Host; if(sUrl[0] == 'h' && sUrl[1] == 't' && sUrl[2] == 't' && sUrl[3] == 'p' && sUrl[4] == ':' && sUrl[5] == '/' && sUrl[6] == '/') // Check if starts with 'http://' { for(unsigned int c = 7; c < sUrl.size(); c++) { tUrl += sUrl[c]; } } else { tUrl = sUrl; } for(unsigned int c = 0; c < tUrl.size(); c++) { if(tUrl[c] == '/') break; Host += tUrl[c]; } Http::Host = Host; return Host; }Allerdings bekomme ich bei dieser anfrage immer den http-error-code 400 zurück (invalid request - der server hat die anfrage nicht "verstanden")
nun... ich hab mir einfach mal wireshark genomm und einmal nen packet von firefox gesniff und einmal das von mir ...
und was raus kommt hier

einmal das packet von firefox (also so wie es wahrscheinlich sein sollte):
http://img827.imageshack.us/img827/9964/rightux.jpgund einmal mein packet...
http://img600.imageshack.us/img600/5558/false.jpgso leute
wär echt super toll wenn mir einer sagen könnte was ich da falsch dran mache ...thx mfg

-
Zwar nicht das Problem, aber -> Augenkrebs!
if(sUrl[0] == 'h' && sUrl[1] == 't' && sUrl[2] == 't' && sUrl[3] == 'p' && sUrl[4] == ':' && sUrl[5] == '/' && sUrl[6] == '/') // Check if starts with 'http://'zu
if(sUrl.find("http://") == 0)
-
Was ist denn dieser zweite "Hypertext Transfer Protocol" Abschnitt auf dem Bild von deinem Paket, das gehört doch nicht dahin, oder? Die Hex-Daten darin heißen "fertig". Ist dir da doch irgendwie noch was rein gerutscht? Im Code hier sehe ich nix verkehrtes.
-
Ist wohl ein "\n" zuviel.
-
Auch nicht das Problem, aber: SendAll macht kein Error-Checking, und das selbe was du bei SendAll machst (in Schleife aufrufen bis alles gesendet wurde) musst du bei recv() auch machen.
Bzw. eigentlich nur bei recv(), denn send() verschickt bei blocking Sockets immer alles, da kann man sich die Schleife auch sparen. Bei recv() wirst du allerdings definitiv ein Problem bekommen, wenn die Antwort mal etwas grösser wird.
-
@fdfdg das frage ich mich ja auch^^... aber da ist eigentlich nichts zwischengerutscht...
@HighLigerBiMBam und wo bitte ;)?
@hustbaer mhh jo ok... aber im moment hab ich halt noch nen viel grösseres problem, als das ich nicht die komplette antwort bekomme^^
thx mfg
-
GET HTTP 1.1 -> Pfad / fehlt und hier auch HTTP**/**1.1.
GET / HTTP/1.1 muss es heissen.
-
hey danke deine antwort war echt hilfreich...
also es lag an folgendem...Meine version:
GET / HTTP 1.1Und so muss es sein:
GET / HTTP/1.1danke bis hier hin
und wenn mir jetzt noch einer sagen könnte wie ich mit großen tcp antworten umgehe bin ich wirklich sehr dankbar 
mfg
-
Http Noob schrieb:
Hey Leute

...naja die grundlagen kann ich aber eigentlich (oop und klassen & syntax etc)...Natürlich

Sieht man auch gut an deinem code.
Kleines Beispiel:Http Noob schrieb:
string Http::GetSubHost(string sUrl) // Example: 'http://google.de/index.php' -> 'google.de' { string tUrl; string bUrl; string Host; if(sUrl[0] == 'h' && sUrl[1] == 't' && sUrl[2] == 't' && sUrl[3] == 'p' && sUrl[4] == ':' && sUrl[5] == '/' && sUrl[6] == '/') // Check if starts with 'http://' { for(unsigned int c = 7; c < sUrl.size(); c++) { tUrl += sUrl[c]; } } else { tUrl = sUrl; } for(unsigned int c = 0; c < tUrl.size(); c++) { if(tUrl[c] == '/') break; Host += tUrl[c]; } Http::Host = Host; return Host; }Alternative:
std::string trim(const std::string& url) { std::string host(url); if (host.find("http://")==0) host.erase(0,7); return host.substr(0,host.find("/")); }
-
Sehr schön du schlaumeier^^
Da ich keine lust hatte mich in die methoden der strings einzulesen hab ichs einfach selfmade erstma gemacht ...
-
Http Noob schrieb:
und wenn mir jetzt noch einer sagen könnte wie ich mit großen tcp antworten umgehe bin ich wirklich sehr dankbar

Du musst recv in einer Schleife aufrufen und zwischen 1. Transfer-Encoding: chunked, 2. Content-Length und 3. Simple (gulp) unterscheiden.
Das wirst du nicht in einem Tag hinkriegen.
also etwa so:
recv bis der header komplett ist, dann den header analysieren und dann wie oben angedeutet fortfahren.
-
Das ist doch in dem Artikel gut erklärt:
-
@EOP: Connection=Close und Content-Length sind relativ einfach hinzubekommen. Und Transfer-Encoding: chunked muss man ja nicht akzeptieren - gibt ja auch noch HTTP 1.0.
-
naja ihr habt mir mit euren tipps schonmal sehr gehilfen bisher

Ich werde da morgen einfach nen bischen rumprobiern werde das schon irgendwie hinbekommen^^thx