2012-05-20 26 views
37

Quando invio una normale richiesta HTTP tramite un socket, il server non risponde con una risposta OK. Ho copiato l'intestazione HTTP da FireFox. Ecco il codice:Invia richiesta HTTP manualmente tramite socket

Socket s = new Socket(InetAddress.getByName("stackoverflow.com"), 80); 
PrintWriter pw = new PrintWriter(s.getOutputStream()); 
pw.print("GET/HTTP/1.1"); 
pw.print("Host: stackoverflow.com"); 
pw.flush(); 
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
String t; 
while((t = br.readLine()) != null) System.out.println(t); 
br.close(); 

Tuttavia, qui è la risposta che ho ricevuto:

HTTP/1.0 408 Request Time-out 
Cache-Control: no-cache 
Connection: close 
Content-Type: text/html 

<html><body><h1>408 Request Time-out</h1> 
Your browser didn't send a complete request in time. 
</body></html> 

So che posso fare questo usando URL.openStream(), ma perché il server non identifica la richiesta HTTP quando lo invio manualmente?

+3

Credo che bisogna inviare un ritorno a capo aggiuntivo dopo tutte le intestazioni; 'pw.println();', e usa 'println()' anche per le intestazioni? – Torious

+0

@Torious Sì, questo è il problema. Grazie :) –

+1

E le nuove righe devono essere di tipo \ r \ n per HTTP. – EJP

risposta

37

due cose:

  1. si dovrebbe usare println invece di print di stampare le voci per separare le linee.
  2. La richiesta HTTP deve terminare con una riga vuota (link). Quindi aggiungi pw.println("");
+0

Perfetto. Aggiungere la riga vuota è importante! – asgs

+1

Funziona solo su macchine Windows. Su Linux, stamperà solo LF invece di CRLF che è necessario per le specifiche HTTP. Guarda le altre risposte. – Xiv

+0

perché fornisce e 'HTTP/1.1 400 Bad Request' quando ho cambiato l'host in' pw.println ("Host: httpstackoverflow.com/questions/10673684/send-http-request-manually-via-socket"); ' – beginner

19

Non segui lo HTTP RFC.

  • linee di intestazione sono sempre chiuso da un LF CR (cioè 0x0d più 0x0a).
  • L'intestazione termina dopo la prima doppia-nuova riga. Nel tuo caso, non includi la newline finale in modo che il server non riconosca la fine delle intestazioni della richiesta.

In generale, si dovrebbe sempre provare a utilizzare le librerie HTTP esistenti. Anche se HTTP sembra essere un protocollo semplice (ed è paragonato ad altri), ha regole sintattiche e semantiche piuttosto rigide. Se si tenta di implementare questo da soli, è necessario aver letto e compreso le parti rilevanti di RFC 2616 (e relative).

Purtroppo, ci sono già troppe implementazioni HTTP schifose che non seguono gli standard là fuori rendendo la vita per tutti infelici. Salva te stesso la seccatura e utilizzare le librerie HTTP della lingua scelta.

+1

+1 per ottenere la parte \ r \ n corretta. – EJP

4

La seguente correzione, come indicato nelle risposte precedenti, risolve il problema;

pw.print("GET/HTTP/1.1\n\r\n"); 
pw.print("Host: stackoverflow.com\n\r\n"); 
8

la correttezza dei fix che funziona davvero ed è cross platform:

pw.print("GET/HTTP/1.1\r\n"); 
    pw.print("Host: stackoverflow.com\r\n\r\n"); 
+0

Ho usato 'Host:' invece di 'Host:' e tutti ricevendo Bad Request (400) e ci è voluto un giorno per rendersene conto, fa davvero schifo. –

Problemi correlati