854 Aufrufe
Gefragt in Anwendungen(Java,C++...) von
Hi
Ich spiel grad so ein bisschen mit den Socket Sachen in C++ rum, und da wollt ich mal "ganz einfach" von Google die Startseite (bzw. erstmal die Header) runterladen. Mein Gedankengang:
-GET HTTP/1.1, senden
-packetweise Startseite empfangen
Nunja, natürlich hat das nicht so einfach funktioniert. Ich bekomme zwar immer Erfolgsmeldungen, aber beim Empfangen kommen immer 0 Bytes an.
Jetzt, bevor hr euch mit dem Code herumschlagt, ist meine Herangehensweise überhaupt die Richtige? Send HTTP-Requestes und dann Inhalt erwarten? Wenn nein, dann könnt ihr euch denCode schenken, womit sollte ich michdann befassen?
Wenn doch, dann:
Der Code meiner main():

WSAData mywsadata;
int mySocket;
sockaddr_in targetServer;


// --- WSASTARTUP---

cout << "WSAStartup: ";
if(WSAStartup(MAKEWORD(2, 2), &mywsadata) != 0)
{ cout << "Fail" << endl; }
else
{ cout << "Erfolg" << endl; }

// ---SOCKET & CONNECT ---

cout << "Socket(): ";
mySocket = socket(AF_INET, SOCK_STREAM, 0);
if(mySocket < 0)
{ cout << "Fail" << endl; }
else
{ cout << "Erfolg" << endl; }

cout << "Connect(): ";

hostent * he = gethostbyname("www.google.com");

targetServer.sin_family = AF_INET;
targetServer.sin_addr.s_addr = *((unsigned long*) he->h_addr);
targetServer.sin_port =htons(80);
if(connect(mySocket, (SOCKADDR *) & targetServer, sizeof(targetServer)) != 0)
{ cout << "Fail" << endl; }
else
{ cout << "Erfolg" << endl; }

// ---SOCKET & CONNECT END---

// ---SEND---

cout << "\nSend: #1 ";
char *myReq = "GET HTTP/1.1";
if(send(mySocket, myReq, (int)strlen(myReq) ,0) == SOCKET_ERROR)
{ cout << "Fail: " << endl; }
else
{ cout << "Erfolg" << endl; }

cout << "\nSend: #2 ";
myReq = "Host: www.google.com";
if(send(mySocket, myReq, (int)strlen(myReq) ,0) == SOCKET_ERROR)
{ cout << "Fail: " << endl; }
else
{ cout << "Erfolg" << endl; }

cout << "\nSend: #3 ";
myReq = "Accept: */*";
if(send(mySocket, myReq, (int)strlen(myReq) ,0) == SOCKET_ERROR)
{ cout << "Fail: " << endl; }
else
{ cout << "Erfolg" << endl; }

cout << "\nSend: #4 ";
myReq = "Connection: close";
if(send(mySocket, myReq, (int)strlen(myReq) ,0) == SOCKET_ERROR)
{ cout << "Fail: " << endl; }
else
{ cout << "Erfolg" << endl; }

// ---SEND END---

// ---SHUTDOWN---

cout << "Shutdown nach Senden: ";
if(shutdown(mySocket, SD_SEND) == SOCKET_ERROR)
{cout << "Fail: " << endl; }
else
{ cout << "Erfolg" << endl; }

// ---EMPFANGEN---

cout << "Empfangen: " << endl;
char recbuf;
int myRecRes;
do{
myRecRes = recv(mySocket, &recbuf, 512, 0);
if(myRecRes > 0)
{
cout << "Empfangene bytes: " << myRecRes << endl;
}
else if(myRecRes == 0)
{
cout << "Connection closed" << endl;
}
else
{
cout << "Fail" << endl;
}
} while(myRecRes > 0);

// ---SOCKET & WSA CLOSE---

cout << "Socket schliessen: ";
if(closesocket(mySocket) != 0)
{ cout << "Fail" << endl; }
else
{ cout << "Erfolg" << endl; }

cout << "WSACleanup: ";
if(WSACleanup() != 0)
{ cout << "Fail" << endl; }
else
{ cout << "Erfolg" << endl; }

int h;
cin >> h;



Und die dazu gehörge Ausgabe:
WSAStartup: Erfolg
Socket(): Erfolg
Connect(): Erfolg

Send: #1 Erfolg

Send: #2 Erfolg

Send: #3 Erfolg

Send: #4 Erfolg
Shutdown nach Senden: Erfolg
Empfangen:
Connection closed
Socket schliessen: Erfolg
WSACleanup: Erfolg


Vielen Dank
Grüße

2 Antworten

0 Punkte
Beantwortet von Experte (3.2k Punkte)
Ohne dein Beispiel selbst testen zu können, ist mir Folgendes aufgefallen:

1. Das shutdown des Sendeteils des Sockets erscheint mir hier unnötig. Vielleicht sogar kontraproduktiv oder fehlerverursachend, aber soweit bin ich aus der MSDN gerade nicht schlau geworden.

2. Würdest du Daten empfangen können, wirst du einen Buffer-Overflow verursachen. dein recbuf ist nämlich genau 1 byte lang, du liest aber bis zu 512.
Sieht mir aber nach nem Flüchtigkeitsfehler aus, der dir auch relativ schnell aufgefallen wäre ;)

3. Dein HTTP-Request ist nicht korrekt. Bedenke, dass send selbst die Daten roh überträgt, also keine Steuerzeichen einfügt.
Da wird dieser Requeststring gesendet:
GET HTTP/1.1Host: www.google.comAccept: */*Connection: close

D.h. es fehlen die Zeilenterminatoren, nämlich \r\n, sowie die leere Zeile am Ende des Requests.
Also müsste dein Request folgendermaßen aussehen:
GET HTTP/1.1\r\nHost: www.google.com\r\nAccept: */*\r\nConnection: close\r\n\r\n


Ansonsten sieht mir der Code auf den ersten Blick richtig aus.

Ele
0 Punkte
Beantwortet von
Hi

Schonmal vorweg: Ich habe den Header mit den Leerzeilen angepasst und - voila ;) Vielen Dank!

Zu 1.: Ja ehrlich gesagt hat mich das auch verwundert gehabt, nur als das nicht geklappt hat, hab ich bei msdn nachgeschlagen, und da war es da. Außerdem hat das Programm ohne den Shutdown ein paar Sekunden gebraucht, bis es Conenction closed angezeigt hat, mit gings aber sofort.

zu 2.: hehe, ja das war... unklug von mir :P

zu 3.: Das macht Sinn, ich dachte aus irgendeinem Grund, dass send immer selber Zeilenumbrüche mit einfügt :P

Wie dem auch sei, es klappt. Nochmals danke :)

Grüße
...