2011-04-22 15 views
14

Me gustaría poder construir una solicitud HTTP sin procesar y enviarla con un socket. Obviamente, te gustaría usar algo como urllib y urllib2 pero no quiero usar eso.Crear una solicitud HTTP sin formato con conectores

tendría que ser algo como esto:

import socket 

tcpsoc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
tcpsoc.bind(('72.14.192.58', 80)) #bind to googles ip 
tcpsoc.send('HTTP REQUEST') 
response = tcpsoc.recv() 

Obviamente también se tendría que solicitar la página/archivo y obtener y los parámetros de correos

+3

Bueno, en principio, es totalmente fácil, envía 'OBTENER HTTP/1.1' seguido de 'Anfitrión: el nombre del servidor' seguido de dos nuevas líneas. Lo que lo complica es que hay un millón de opciones y un millón de posibles respuestas que debes analizar (es por eso que uno debería decir "usa una biblioteca"). – Damon

+3

necesita tcpsoc.connect en lugar de bind. bind es para sockets de escucha ... – Milan

+1

he aquí un ejemplo de connect: http://docs.python.org/library/socket.html#example – Milan

Respuesta

12

mayor parte de lo que necesita saber está en el HTTP/1.1 spec, que definitivamente debe estudiar si quieres rodar su propia aplicación HTTP: http://www.w3.org/Protocols/rfc2616/rfc2616.html

+7

reglas de RFC! (en ambos sentidos de las palabras ...) –

6

Sí, básicamente, sólo hay que escribir el texto, algo como:

GET /pageyouwant.html HTTP/1.1[CRLF] 
Host: google.com[CRLF] 
Connection: close[CRLF] 
User-Agent: MyAwesomeUserAgent/1.0.0[CRLF] 
Accept-Encoding: gzip[CRLF] 
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7[CRLF] 
Cache-Control: no-cache[CRLF] 
[CRLF] 

Siéntase libre de quitar/agregar encabezados a voluntad.

+0

¡Hola! ¿Cuál es el nombre del texto anterior? 'Solicitud en bruto',' Mensaje en bruto' u otro? – hasanghaforian

+0

@hasanghaforian: si sigue siendo relevante, el texto completo se llama * encabezado HTTP *. Opcionalmente, es seguido por el contenido real, separado por una línea vacía. Este es el caso, cuando envía una respuesta al cliente de cargar datos al servidor. – linusg

+0

@linusg ¡Gracias por tu respuesta! – hasanghaforian

0

Para un ejemplo de trabajo para guiar a usted, es posible que desee a echar un vistazo a libcurl, una biblioteca escrito en el lenguaje C que:

  1. hace lo que quiere y mucho más;

  2. es fácil de usar;

  3. es ampliamente utilizado; y

  4. es compatible de forma activa.

Es una cosa hermosa y uno de los mejores ejemplos de lo que puede y debe ser de código abierto.

23
#!/usr/bin/python 

import socket 
import urlparse 
import re 
import os 

socket.setdefaulttimeout = 0.50 
os.environ['no_proxy'] = '127.0.0.1,localhost' 
linkRegex = re.compile('<a\s*href=[\'|"](.*?)[\'"].*?>') 
CRLF = "\r\n\r\n" 


def GET(url): 
    url = urlparse.urlparse(url) 
    path = url.path 
    if path == "": 
     path = "/" 
    HOST = url.netloc # The remote host 
    PORT = 80   # The same port as used by the server 
    # create an INET, STREAMing socket 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    """ 
    *********************************************************************************** 
    * Note that the connect() operation is subject to the timeout setting, 
    * and in general it is recommended to call settimeout() before calling connect() 
    * or pass a timeout parameter to create_connection(). 
    * The system network stack may return a connection timeout error of its own 
    * regardless of any Python socket timeout setting. 
    *********************************************************************************** 
    """ 
    s.settimeout(0.30) 
    """ 
    ************************************************************************************** 
    * Avoid socket.error: [Errno 98] Address already in use exception 
    * The SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state, 
    * without waiting for its natural timeout to expire. 
    ************************************************************************************** 
    """ 
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    #s.setblocking(0) 
    s.connect((HOST, PORT)) 
    s.send("GET/HTTP/1.0%s" % (CRLF)) 
    data = (s.recv(1000000)) 
    print data 
    # https://docs.python.org/2/howto/sockets.html#disconnecting 
    s.shutdown(1) 
    s.close() 
    print 'Received', repr(data) 

GET('http://www.google.com') 
+1

Necesito revisar esto. –

Cuestiones relacionadas