Sockets und das HTTP-Protokoll



  • Was für ein eingescanntes schrieb:

    Tim schrieb:

    Das eingescannte Bild ist einfach nur cool 🕶 👍

    Was für ein eingescanntes Bild?

    Das, das ersetzt wurde.



  • Hallo miteinander, 😃

    ich hab mich jetzt in dieses Tutorial reingearbeitet. Leider liefert mein IIS folgenden Response zurück:

    HTTP/1.1 100 Continue
    
    Server: Microsoft-IIS/5.1
    
    Date: Wed, 26 Mar 2008 17:29:40 GMT
    
    HTTP/1.1 200 OK
    
    Server: Microsoft-IIS/5.1
    
    Date: Wed, 26 Mar 2008 17:29:40 GMT
    
    Connection: close
    
    X-Powered-By: ServletExec/5.0p06, Servlet/2.4, JSP/2.0
    
    Content-Type: text/html; charset=UTF-8
    
    Cache-Control: no-cache
    
    Set-Cookie: JSESSIONID=2ZeunHRcvNeHrcmBfYa9cw1yilk; path=/arsys
    

    Aufgrund dessen läuft die GetLine Funktion in eine Endlosschleife -> Absturz. Probiere jetzt schon seit Tagen herum. Ich versuche dieses Tutorial auf alle Webserver (Apache,Tomcat,IIS) zum laufen zu bekommen.

    Danke für eure Hilfe! 🤡



  • Hallo 😃

    monoid schrieb:

    Hallo miteinander, 😃

    ich hab mich jetzt in dieses Tutorial reingearbeitet. Leider liefert mein IIS folgenden Response zurück:

    HTTP/1.1 100 Continue
    
    Server: Microsoft-IIS/5.1
    
    Date: Wed, 26 Mar 2008 17:29:40 GMT
    
    HTTP/1.1 200 OK
    
    Server: Microsoft-IIS/5.1
    
    Date: Wed, 26 Mar 2008 17:29:40 GMT
    
    Connection: close
    
    X-Powered-By: ServletExec/5.0p06, Servlet/2.4, JSP/2.0
    
    Content-Type: text/html; charset=UTF-8
    
    Cache-Control: no-cache
    
    Set-Cookie: JSESSIONID=2ZeunHRcvNeHrcmBfYa9cw1yilk; path=/arsys
    

    Aufgrund dessen läuft die GetLine Funktion in eine Endlosschleife -> Absturz.

    Aufgrund von was?
    Könntest du mir die URL (d)eines IIS-Servers geben, dann kann ich das selber ausprobieren.



  • So! Hallo mal wieder!

    Nach Monaten Abwesenheit bin ich auch mal wieder da 🙂 und natürlich brauche ich mal wieder Eure Hilfe.

    Wie im Thread schon mal erwähnt, habe ich einen Teil dieses Samples erfolgreich in meinem Programm verbaut, das schöne ist halt, dass das alles ohne weitere Libs, .NET oder sonst was läuft.
    Jetzt habe ich einen Umbau vor und müßte dazu einen Post-Request erzeugen. Da ich hier nur Get-Beispiele finde und aus der W3-Protokoll-Doku nicht gänzlich schlau werde, frage ich hier mal nach.
    Vielleicht hat ja jmd. die notwendigen zusätzlichen Zeilen, die Grundform sollte ja die selbe sein.

    THX!





  • SammyRukka schrieb:

    ...und aus der W3-Protokoll-Doku nicht gänzlich schlau werde,...

    ...und Du meinst, mit dem Link wird's besser... :p hast Du ein Vertrauen!

    Aber OK, ich werd's mal durchforsten und hoffen, dass ich daraus sinnvollen Code gießen kann. thx so far



  • SammyRukka schrieb:

    ...und Du meinst, mit dem Link wird's besser... :p hast Du ein Vertrauen!

    die seite gibts schon ziemlich lange. ich hab' damals 'nen kleinen webserver gecodet und hatte 0 ahnung von http. ich hab' fast alles, was man dafür wissen muss von dieser seite.
    btw, hier ist ein einfaches beispiel u.a. mit POST request: http://dev.makingthings.com/browser/firmware/trunk/controller/makingthings/webclient.c
    🙂



  • Na das ist doch mal etwas Greifbares. Danke! Ich schau mal.





  • Hi bei mir wird das Programm immer mit "Verbindung fehlgeschlagen!" beendet. Kann es daran iegen das indem Netzwerk wo ich bin alle browser nur mit einem Proxy laufen?
    Wie kann man das beheben?



  • Ja das könnte daran liegen. Ich aber leider keine Ahnung, wie man das beheben kann. Am besten eröffne mal einen Thread im Linux- oder WinAPI-Forum.



  • Ich habe gerade ein Programm geschrieben, das eine Webseite herunterlädt. Wenn ich HTTP/1.0 nutze, dann klappt alles, aber nutze ich HTTP/1.1, dannn werden am Ende und Anfang noch einige Dinge mitgesendet, die da nicht hingehören, denke ich. Ich bin übrigens nicht nach Content-Length gegangen, sondern habe gewartet bis der Server trennt(Connection: Close)...

    Hier die Ausgabe:

    'HTTP/1.1 200 OK
    '
    'Date: Sat, 08 Nov 2008 18:33:37 GMT
    '
    'Server: Apache/2.2.3 (Debian) PHP/4.4.4-8+etch6
    '
    'X-Powered-By: PHP/4.4.4-8+etch6
    '
    'Set-Cookie: POSTNUKESID=40a9782024010d53f011b6e64fc72f17; expires=Wed, 09 Nov 2033 00:33:37 GMT; path=/cms
    '
    'Expires: Thu, 19 Nov 1981 08:52:00 GMT
    '
    'Cache-Control: cache
    '
    'Pragma: no-cache
    '
    'Connection: close
    '
    'Transfer-Encoding: chunked
    '
    'Content-Type: text/html
    '
    '
    '
    '47b2
    '
    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
    '<html>'
    '<head>'
    '<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">'
    '<title>c++.de :: Irgendwer hat immer eine Antwort</title>'
    '<meta name="KEYWORDS" content="C++, Software, C, C#, STL, OOP, OOA, Objektorientierte Programmierung, Softwareentwicklung, Tutorials, Compiler, Bücher, ebooks, IDE, Programmierung, Proggen, c++.de, Decompiler, Visual, MFC, VCL, main, if, while, else, for, Objekt, .NET, net, gtkmm, qt, wxWidgets, GUI, Dialog, Fenster, Anwendung">'
    '<meta name="DESCRIPTION" content="Irgendwer hat immer eine Antwort">'
    '<meta name="ROBOTS" content="INDEX,FOLLOW">'
    '<meta name="resource-type" content="document">'
    [usw......]
    'pageTracker._trackPageview();'
    '</script></body>'
    '</html>
    '
    '0
    '
    '
    '

    Warum? Die ' sind nur zum besseren Debugen und im Original nicht vorhanden. Habt ihr das Problem bei http://www.c-plusplus.net auch oder ist mein Programm fehlerhaft? Aber warum geht es dann perfekt(!) mit HTTP/1.0 aber mit HTTP/1.1 nicht?

    Danke für die Hilfe,
    VerzweifelterMensch



  • Für solche Fragen eröffne bitte einen Thread im Linux- oder WinAPI-Forum.

    Schau dir Kapitel 6.4 Chunked Transfer-Encoding nochmal an.



  • hi,

    bin im Kapitel 6.4 und hab da alles fertig !
    Aber irgendwie und aus irgendeinem grund funktioniert der code bei mir nicht !

    Hab alles genauso, aber trotzdem geht es bis zur prozentanzeige, da steht dann eben 0% und dann kommt "Socket-Fehler #0: D"
    hab meinem code mit dem code von hier verglichen, finde aber nix und wenn ich den code, den ich hier downgeloadet hab, ausprobier, dann funktioniert er, bloß mein selbst geschriebener nicht !

    Verstehe ich nicht, weiß jemand rat, gibts noch irgendwas zu beachten ??

    Hier mein Code:

    #include <iostream>
    #include <fstream>
    #include <stdexcept>	// runtime_error
    #include <sstream>
    #include <string>
    #include <WinSock2.h>
    using namespace std;
    // Infos: http://www.c-plusplus.net/forum/viewtopic-var-t-is-169861.html
    
    // wenn während dem Senden ein Fehler auftritt
    runtime_error CreateSocketError()
    {
    	ostringstream temp;
    	int error = WSAGetLastError();
    	temp << "Socket-Fehler #" << error;
    	char *msg;
    
    	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    		reinterpret_cast<LPWSTR>(&msg), 0, NULL))
    	{
    		try
    		{
    			temp << ": " << msg;
    			LocalFree(msg);
    		}
    		catch (...)
    		{
    			LocalFree(msg);
    			throw;
    		}
    	}
    	return runtime_error(temp.str());
    }
    
    // um restlichen Buffer noch zu senden, falls send eher aufhört zu senden 
    void SendAll(int socket, const char* const buf, const int size)
    {
    	int bytesSent = 0;	// Anzahl Bytes, die bereits vom Buffer gesendet wurden
    	do 
    	{
    		int result = send(socket, buf + bytesSent, size - bytesSent, 0);
    		if (result < 0)
    		{
    			throw CreateSocketError();
    		}
    		bytesSent += result;
    	} while (bytesSent < size);
    }
    
    // liest eine Zeile des Socket in Stringstream (HTTP-Protokoll sendet zeilenweise)
    void GetLine(int socket, stringstream &line)
    {
    	// byteweise von Socket lesen, bis Zeilenumbruch auftritt
    	for (char c; recv(socket, &c, 1, 0) > 0; line << c)
    	{
    		if (c == '\n')
    		{
    			return;
    		}
    	}
    	throw CreateSocketError();	// wenn recv < 0 || = 0 ist, 
    }
    
    int main()
    {
    	WSADATA w;
    	// man will Zugriff auf Winsock-Lib haben
    	if (int result = WSAStartup(MAKEWORD(2,2), &w) != 0)
    	{
    		cout << "Winsock 2 konnte nicht gestartet werden! Error: " << result << endl;
    		return 1;
    	}
    	hostent *phe = gethostbyname("www.kernel.org");
    	if (phe == NULL)
    	{
    		cout << "Host konnte nicht aufgeloest werden!\n";
    		return 1;
    	}
    	if (phe->h_addrtype != AF_INET)
    	{
    		cout << "ungueltiger Adress-Typ!\n";
    		return 1;
    	}
    	if (phe->h_length != 4)
    	{
    		cout << "Ungueltiger IP-Typ!\n";
    		return 1;
    	}
    
    	SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if (Socket == -1)
    	{
    		cout << "Socket konnte nicht erstellt werden!\n";
    		return 1;
    	}
    
    	sockaddr_in service;
    	service.sin_family = AF_INET;	// für IPv4
    	service.sin_port = htons(80);	// Port 80 nutzt HTTP
    
    	// Iterator
    	char **p = phe->h_addr_list;	// p mit 1. Listenelement initialisieren
    	int result;						// Ergebnis von connect
    	do 
    	{
    		// Liste zu Ende ?
    		if (*p == NULL)
    		{
    			cout << "Verbindung fehlgeschlagen!\n";
    			return 1;
    		}
    		service.sin_addr.s_addr = *reinterpret_cast<unsigned long*>(*p);
    		++p;
    		result = connect(Socket, reinterpret_cast<sockaddr*>(&service), sizeof(service));
    
    	} while (result == -1);
    
    	cout << "Verbindung erfolgreich!\n";
    	const string request = "GET /faq/index.html HTTP/1.1\r\nHost: www.kernel.org\r\nConnection: close\r\n\r\n";
    
    	try
    	{
    		SendAll((int)Socket, request.c_str(), (int)request.size());
    		int code = 100;		// 100 = continue
    		string protokoll;
    		stringstream firstLine;
    		while (code == 100)
    		{
    			GetLine((int)Socket, firstLine);
    			firstLine >> protokoll;
    			firstLine >> code;
    			if (code == 100)
    			{
    				GetLine((int)Socket, firstLine);	// leere Zeile nach continue ignorieren
    			}
    		}
    		cout << "Protokoll: " << protokoll << endl;
    		if (code != 200)
    		{
    			firstLine.ignore();
    			string msg;
    			getline(firstLine, msg);
    			cout << "Error #" << code << " - " << msg << endl;
    			return 0;
    		}
    
    		bool chunked = false;		// wurde Transfer-Encoding: chunked angegeben ?
    		const int noSizeGiven = -1;
    		int size = noSizeGiven;		// speichert übergebene Dateigröße
    
    		while (true)
    		{
    			stringstream sstream;
    			GetLine((int)Socket, sstream);
    			if (sstream.str() == "\r")		// Header zu Ende
    			{
    				break;
    			}
    			string left;
    			sstream >> left;
    			sstream.ignore();		// Leerzeichen ignorieren
    
    			if (left == "Content-Length:")
    			{
    				sstream >> size;
    			}
    			if (left == "Transfer-Encoding:")
    			{
    				string transferEncoding;
    				sstream >> transferEncoding;
    				if (transferEncoding == "chunked")
    				{
    					chunked = true;
    				}
    			}
    		}
    
    		fstream out("faq.html", ios::binary|ios::out);
    		if (!out)
    		{
    			cout << "Could not create File!" << endl;
    			return 1;
    		}
    
    		int recvSize = 0;		// empfangene Bytes insgesamt
    		char buffer[1024];
    		int bytesRecv = -1;		// empfangene Bytes des letzten recv
    
    		if (size != noSizeGiven)	// wenn Größe über Content-Length gegeben wurde
    		{
    			cout << "0%";
    			while (recvSize < size)
    			{
    				if (bytesRecv = recv(Socket, buffer, sizeof(buffer), 0) <= 0)
    				{
    					throw CreateSocketError();
    				}
    				// empfange Anzahl an Bytes zu Gesamtanzahl addieren und Buffer in Datei schreiben
    				recvSize += bytesRecv;
    				out.write(buffer, bytesRecv);
    				cout << "\r" << recvSize * 100 / size << "%" << flush;	// mit \r an Anfang der Zeile springen
    			}
    		}
    		else
    		{
    			if (!chunked)
    			{
    				cout << "Downloading... (Unknown FileSize)" << endl;
    				while (bytesRecv != 0)
    				{
    					if (bytesRecv = recv(Socket, buffer, sizeof(buffer), 0) < 0)
    					{
    						throw CreateSocketError();
    					}
    					out.write(buffer, bytesRecv);
    				}
    			}
    			else
    			{
    				cout << "Donwloading... (Chunked)" << endl;
    				while (true)
    				{
    					stringstream sstream;
    					GetLine((int)Socket, sstream);
    					int chunkSize = -1;
    					sstream >> hex >> chunkSize;	// Größe des nächsten Parts einlesen
    					if (chunkSize <= 0)
    					{
    						break;
    					}
    					cout << "Downloading Part (" << chunkSize << " Bytes)..." << endl;
    					recvSize = 0;					// vor jeder Schleife wieder auf 0 setzen
    					while (recvSize < chunkSize)
    					{
    						int bytesToRecv = chunkSize - recvSize;
    						// an recv als Größe entweder sizeof(buf) oder aber bytesToRecv übergeben, wenn nur noch ein kleines Stück empfangen werden muss 
    						if (bytesRecv = recv(Socket, buffer, bytesToRecv > sizeof(buffer) ? sizeof(buffer) : bytesToRecv, 0) <= 0)
    						{
    							throw CreateSocketError();
    						}
    						recvSize += bytesRecv;
    						out.write(buffer, bytesRecv);
    						cout << "\r" << recvSize * 100 / chunkSize << "%" << flush;
    					}
    					cout << endl;
    					for (int i = 0; i < 2; ++i)
    					{
    						char temp;
    						recv(Socket, &temp, 1, 0);
    					}
    				}
    			}
    		}
    		cout << endl << "Finished!" << endl;
    	}
    	catch (exception &e)
    	{
    		cout << endl;
    		cerr << e.what() << endl;
    	}
    
    	closesocket(Socket);
    
    	cin.get();
    	return 0;
    }
    

    eben derselbe

    -----EDIT-----

    gelöst, muss jeweils so heißen:

    if ((bytesRecv = recv(Socket, buffer, sizeof(buffer), 0)) <= 0)
    

    Klammern übersehen 😉

    thx
    mfg



  • Hallo zusammen
    ist es hiermit auch möglich normale datein wie z.b. Zip Dateien zu downloaden.
    Und wenn nicht könnte mir dann evtl. jemanden sagen wie ich da vorgehen muss.

    Hab mir so ein ähnliches programm geschrieben aber kann irgendwie keine zip,exe usw. Dateien downloaden bekomm dann immer nen Fehler vom Server das die Datei nicht gefunden wurde.



  • Takti schrieb:

    Hallo zusammen
    ist es hiermit auch möglich normale datein wie z.b. Zip Dateien zu downloaden.
    Und wenn nicht könnte mir dann evtl. jemanden sagen wie ich da vorgehen muss.

    Ja, ist damit möglich. Wobei ich eher eine Library wie libcurl (http://curl.haxx.se/ ) nehmen würde.



  • Hallo
    Ich hab ma ne Frage. Hatt jmd vllt ein Tutorial das genau das Gegenteil macht sprich einen Server??



  • wie müsste man den code jetzt erweitern damit das auch mit proxies funktioniert?



  • Hallo, ich benutze Microsoft Visual Studio und habe Standard C/C++ Kenntnisse, jedoch komme einfach nicht an diesen Linker Fehlermeldungen vorbei:

    Fehler 2 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__connect@12" in Funktion "_main". main.obj
    Fehler 3 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__inet_addr@4" in Funktion "_main". main.obj
    Fehler 4 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__htons@4" in Funktion "_main". main.obj
    Fehler 5 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__socket@12" in Funktion "_main". main.obj
    Fehler 6 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSAStartup@8" in Funktion "_main". main.obj
    Fehler 7 fatal error LNK1120: 6 nicht aufgelöste externe Verweise. C:\Users\Jan\msvc\Sockets\Debug\Sockets.exe

    Mein Code sieht so aus:

    #include <iostream>
    #include <winsock2.h>
    using namespace std;
    
    #define IP "79.233.22.28"
    #define PORT 80
    
    int main() {
    	WSADATA wsa;
    	int s;
    	sockaddr_in service;
    	int result;
    
    	if(result = WSAStartup(MAKEWORD(2,2), &wsa) != 0) {
    		cout << "WinSock Library couldn't be loaded!" << endl;
    		cout << "Error: " << result << endl;
    		return 1;
    	}
    
    	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    	if(s == -1) {
    		cout << "Socket couldn't be set up!" << endl;
    		return 1;
    	}
    
    	service.sin_family = AF_INET;
    	service.sin_port = htons(PORT);
    	service.sin_addr.s_addr = inet_addr(IP);
    	result = connect(s, reinterpret_cast<sockaddr*>(&service), sizeof(service));
    
    	if(result == -1) {
    		cout << "Connection couldn't be established!" << endl;
    		return 1;
    	}
    	cout << "Connection established!" << endl;
    	closesocket(s);
    }
    

    Kann mir damit jemand weiterhelfen?
    Vielen Dank schon mal im voraus!



  • Sollten Sie Nutzer der MS VisualC++ IDE sein, müssen Sie die WS2_32.lib Bibliothek dem Linker bekannt geben. Dazu gehen Sie unter Projekt->Eigenschaften->Linker und tragen, wie im Screenshot zu sehen, die Library unter "Zusätzliche Abhängigkeiten" ein:

    http://www.c-plusplus.net/magazin/bilder/sockets_und_das_http-protokoll/03.png


Anmelden zum Antworten