Forum: Postdata

Forum huvudsida -> Programmering -> Postdata

Sidor: 1

Till botten

achnorr 20:33 - 3:e Mars 2008 | Post #1
Medlem
Inlägg: 82


Skicka PM
hur skickar man postdata i c++ (winsock) till en webserver och hur hämtar man sedan resultatet ? är det bara att anväda GET då? tänkte göra ett litet program som loggade in på en sida bara för skojjs skull.

-------------------------
Ohhoo*



sdac 21:54 - 3:e Mars 2008 | Post #2
Medlem
Inlägg: 235


Skicka PM
    Citat av achnorr:
hur skickar man postdata i c++ (winsock) till en webserver och hur hämtar man sedan resultatet ? är det bara att anväda GET då? tänkte göra ett litet program som loggade in på en sida bara för skojjs skull.


Kör du en POST behöver absolut inte köra en GET efteråt för att få svaret. Undantaget är vid en omdirigering (Statuskoder mellan 300 och 399).

Anslut till server, och skicka data enligt HTTP-standarden. Exempel:

  1. POST /uri/till/filen.php HTTP/1.1
  2. Host: host.com
  3. Content-Type: text/plain
  4. Content-Length: 15
  5.  
  6. h=x&y=z&nisse=1


Varje ny rad är ascii 13 följt av ascii 10, det kan du skriva som "\r\n" i strängar. Det finns även betydligt fler typer av POST, men detta är den enklaste.

Sedan när du får tillbaka svaret måste du avgöra överföringskodningen genom att titta på headern "Transfer-Encoding". Vid "chunked" kommer du att ta emot datan i bitar (chunks), tillsammans med ett tal i HEX som anger bitens längd. Exempel:

  1. ... headers ...
  2.  
  3. F
  4. ABCDEFGHIJKLMNOP
  5. 2
  6. ab
  7. 0


I ovan tar du emot två chunks, en med storlek 16 och en med storlek 2. Slutet på överföringen specificeras med en tom chunk, dvs endast "0".

I det andra fallet tar du emot headern "Content-Length", i detta fall behöver ud inte samla ihop chunks, utan du får så mycket som anges av headern Content-Length. Värdet på headern är decimalt.

I vissa fall kommer du att ta emot datan i komprimerad version, för att undvika detta (och således undvika att behöva länka och använda dekomprimeringsbibliotek) använder du dig utav headern "Accept-Encoding" som du själv måste skicka med.

Googla på "HTTP/1.1 Standard Specification" för att läsa mer.

Och nu till mitt svar: Du har två val. Om du fann informationen ovan intressant, läs då om HTTP-standarden och använd vanliga sockets. Om du å andra sidan fann informationen ovan ointressant, använd då ett externt bibliotek för att utgöra det du vill. Jag kan rekommendera libcurl, det är oslagbart.



Senast redigerad 21:55 - 3:e Mars 2008


achnorr 07:45 - 4:e Mars 2008 | Post #3
Medlem
Inlägg: 82


Skicka PM
hur skriver jag till en speciellt fällt eller ruta som jag vill fylla i då?

-------------------------
Ohhoo*



ozamosi 08:04 - 4:e Mars 2008 | Post #4
Administratör
Inlägg: 1129


Skicka PM
Alla fält har ett attribut name. värdet på det attributet är namnet på variabeln som skickas i POST:en. Eller missuppfattar jag frågan?

Utan att på något sätt uppmana dig att låta bli att ställa frågor här, så måste jag ändå rekomendera Wireshark (eller valfritt annat paketsniffningsprogram) om det du vill göra är att reproducera nätverkstrafik. Då kan du starta sniffning av nätverkskortet, göra - i det här fallet - en inloggning, och sedan leta rätt på inloggningspaketet för att få se exakt vad som skickades.

-------------------------
Ljusblå



achnorr 07:37 - 5:e Mars 2008 | Post #5
Medlem
Inlägg: 82


Skicka PM
får inte det riktigt att fungera. aja här är koden
  1. send(sockfd,"POST /index.php HTTP/1.0\r\n",26,0);
  2. send(sockfd,"Host: www.blinkenlights.se\r\n",28,0);
  3. send(sockfd,"Content-Type: text/plain\r\n",26,0);
  4. send(sockfd,"username=achnorr&password=1234\r\n",49,0);
  5. send(sockfd,"\r\n\r\n",4,0);
  6.  
  7.  
  8. while(recv(sockfd,buf,1024,0) !=0)
  9. {
  10. file.open("sida.html");
  11. file << buf;
  12. }
  13.  
  14. closesocket(sockfd);
  15. file.close();


-------------------------
Ohhoo*



ozamosi 07:41 - 5:e Mars 2008 | Post #6
Administratör
Inlägg: 1129


Skicka PM
Du måste ha två radbrytningar mellan headersarna och innhållet - lägg därför till ett \r\n till på rad 3.

-------------------------
Ljusblå



achnorr 14:30 - 5:e Mars 2008 | Post #7
Medlem
Inlägg: 82


Skicka PM
hm blir ändå inte inloggad .. är det ngt mer man måste skrivaSmiley är ganska ny på att använda winsock
  1. send(sockfd,"POST /index.php HTTP/1.0\r\n",26,0);
  2. send(sockfd,"Host: www.blinkenlights.se\r\n",28,0);
  3. send(sockfd,"Content-Type: text/plain\r\n",26,0);
  4. send(sockfd,"\r\n",2,0);
  5. send(sockfd,"username=achnorr&password=1234\r\n",32,0);
  6. send(sockfd,"\r\n\r\n",4,0);
  7.  
  8.  
  9. file.open("sida.html");
  10. cout<<"downloading page..\n";
  11. while(recv(sockfd,buf,1024,0) !=0)
  12. {
  13. file << buf;
  14. }
  15. cout<<"finnished";
  16.  
  17. closesocket(sockfd);
  18. file.close();
  19. cin.get();


-------------------------
Ohhoo*



ozamosi 14:40 - 5:e Mars 2008 | Post #8
Administratör
Inlägg: 1129


Skicka PM
Jag har aldrig använt winsock, men...

Vad gör du på rad 9 egentligen!?

-------------------------
Ljusblå



achnorr 14:58 - 5:e Mars 2008 | Post #9
Medlem
Inlägg: 82


Skicka PM
    Citat av ozamosi:
Vad gör du på rad 9 egentligen!?

eh, öppnar/skapar en fil som jag ska skriva till?


-------------------------
Ohhoo*



sdac 20:38 - 5:e Mars 2008 | Post #10
Medlem
Inlägg: 235


Skicka PM
    Citat av achnorr:
hm blir ändå inte inloggad .. är det ngt mer man måste skrivaSmiley är ganska ny på att använda winsock
  1. send(sockfd,"POST /index.php HTTP/1.0\r\n",26,0);
  2. send(sockfd,"Host: www.blinkenlights.se\r\n",28,0);
  3. send(sockfd,"Content-Type: text/plain\r\n",26,0);
  4. send(sockfd,"\r\n",2,0);
  5. send(sockfd,"username=achnorr&password=1234\r\n",32,0);
  6. send(sockfd,"\r\n\r\n",4,0);



Du specificerar inte content length, servern kan omöjligtvis veta hur mycket data du ska skicka och blir tvungen att a) vänta tills du stänger anslutningen (och därmed slumpar svaret), eller b) slänga bort din HTTP-förfrågan, beroende på servermjukvaran.

Byt till http/1.1 och sätt headern "Content-Length" till längden på datan du skickar. Du verkar ha lite för bråttom, det här är inte lego vi leker med, utan strikta protokoll. Låt mig citera HTTP/1.0-standarden:
"A valid Content-Length is required on all HTTP/1.0 POST requests."

Sen så förväntar sig servern säkerligen inte varje header separerat i olika TCP-paket (Jag har själv varit med om problem när jag skickat på det sättet)... Skicka allt i ett paket, dvs en send(), eller headers för sig och data för sig. Du behöver heller inte avsluta din förfrågan med TRE(?) st "\r\n"...


  1. file.open("sida.html");
  2. cout<<"downloading page..\n";
  3. while(recv(sockfd,buf,1024,0) !=0)
  4. {
  5. file << buf;
  6. }


... buf är visserligen fylld med data, med det är inte en STR,,NG. Den är således inte null-avslutad, och riskerar att innehålla '\0' vart som helst (även om detta borde vara ovanligt). Använd vettiga funktioner för att skriva till filen istället. Håll dig undan från C++ när du ändå blandar in C. C++ gömmer nämligen vad som ligger bakom koden, skapar missförstånd och dålig inblick, samt buggar (som bevisat av din kod).

Mer korrekt lösning:
  1. int n;
  2. while ((n = recv(sockfd, buf, 1024, 0)) != 0 && n != -1)
  3. fwrite(buf, 1, n, fp);

... där fp är en variabel av typen FILE* som du öppnat filen till via fopen().

recv() returnerar -1 om anslutningen bröts, och 0 om anslutningen stängdes.

EDIT:
Vid närmare eftertanke tycker jag att du ska köra HTTP/1.0 istället (som du hade först). Annars finns risken att loopen som hämtar data fortsätter efter det att informationen du vill ha är hämtad, eftersom HTTP/1.1 tillåter flera förfråganden och svar under samma anslutning.

Frågan är bara om det finns risk att servern svarar i HTTP/1.1 fastän du utförde en förfrågan i HTTP/1.0, om så är fallet måste du antingen läsa Content-Length eller läsa chunks, för att slutligen stänga anslutningen själv. Alternativt förlita dig på headern "Connection: close" och behålla den HTTP/1.0-kompatibla loopen.


Senast redigerad 20:58 - 5:e Mars 2008


Sidor: 1

Forum huvudsida -> Programmering -> Postdata
Atom feed

Du får inte posta i den här tråden | Till toppen