Desde las otras publicaciones en el desbordamiento de pila, esto debería estar funcionando

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                 

s.connect(("www.cnn.com" , 80))
s.sendall("GET / HTTP/1.1\r\n")
print s.recv(4096)
s.close

Pero por alguna razón simplemente se cuelga (en recv) y nunca se imprime. Sé que una solicitud a www.cnn.com fragmentará sus datos, pero al menos debería leer algo de recv, ¿verdad?

PD. Sé que esta no es la mejor manera de hacerlo y que hay bibliotecas como httplib y urllib2, pero no puedo usarlas para este proyecto (es para la escuela). Tengo que usar la biblioteca socket

10
james smith 10 dic. 2015 a las 04:15

6 respuestas

La mejor respuesta

Olvidó enviar una línea en blanco después de su línea de solicitud:

s.sendall("GET / HTTP/1.1\r\n\r\n")

Además, HTTP 1.1 especifica que debe agregar el campo de encabezado Host como se documenta en Sección de host en el HTTP 1.1 RFC.

s.sendall("GET / HTTP/1.1\r\nHost: www.cnn.com\r\n\r\n")
15
Takis 10 dic. 2015 a las 01:29

Lamento perder el tiempo de todos. Acabo de encontrar esta solución aquí en Stack Overflow (solo tomé algunas palabras nuevas en mi búsqueda de Google para encontrar)

import socket
request = b"GET / HTTP/1.1\nHost: www.cnn.com\n\n"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("cnn.com", 80))
s.send(request)
result = s.recv(10000)
while (len(result) > 0):
    print(result)
    result = s.recv(10000)

Y todas las respuestas también fueron correctas sobre el final \r\n\r\n, sin embargo, esas devolvieron los 301 estados. Esta solución parece seguir la redirección de alguna manera? De todos modos, estas soluciones me funcionaron

6
Community 23 may. 2017 a las 10:28

@james: hiciste un ataque SlowLoris allí sin darte cuenta. No puedo explicar mejor que aquí, https://www.youtube.com/watch?v = XiFkyR35v2Y Asumí que encontraste la solución de todas las respuestas anteriores, pero acabo de responder para que lo sepas. :)

0
sibi 4 dic. 2019 a las 13:27

Su código es casi correcto, pero necesita enviar 2 secuencias \r\n para satisfacer el protocolo HTTP.

Una solicitud GET válida se verá así (nota 2 líneas):

GET / HTTP/1.1

Entonces su código debería ser:

s.sendall('GET / HTTP/1.1\r\n\r\n')

Además de eso, hay encabezados adicionales necesarios para solicitudes HTTP 1.1 válidas, como Host:. Debe agregarlos a su solicitud, algo como esto:

s.sendall('''GET / HTTP/1.1
Host: cnn.com

''')
7
mhawke 10 dic. 2015 a las 01:40

Estoy limpiando los ejemplos para Python 3. Necesitamos conversión de bytes / cadena y también podemos usar el cierre automático de la conexión usando with:

#!/usr/bin/env python3

import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

    s.connect(("example.com" , 80))
    s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\nAccept: text/html\r\n\r\n")
    print(str(s.recv(4096), 'utf-8'))
1
Jan Bodnar 6 sep. 2019 a las 09:00

Intenta reemplazar esta línea:

s.sendall("GET / HTTP/1.1\r\n")

Con:

s.sendall("GET / HTTP/1.1\r\n\r\n")
                             ^^^^

Además, creo que necesita reemplazar s.close con s.close() ya que es una función.

1
Kevin Guan 10 dic. 2015 a las 01:21