Создание необработанного HTTP-запроса с сокетами

Я хотел бы иметь возможность построить необработанный HTTP-запрос и отправить его с помощью сокета. Очевидно, вы хотели бы, чтобы я использовал что-то вроде urllib и urllib2, но я не хочу использовать это.

Это должно выглядеть примерно так:

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()

Очевидно, вам также нужно будет запросить страницу/файл и получить и опубликовать параметры

Ответы

Ответ 1

Большая часть того, что вам нужно знать, - это спецификация HTTP/1.1, которую вам обязательно нужно изучить, если вы хотите запустить собственную реализацию HTTP: http://www.w3.org/Protocols/rfc2616/rfc2616.html

Ответ 2

#!/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')

Ответ 3

Да, в основном вам просто нужно написать текст, например:

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]

Не стесняйтесь удалять/добавлять заголовки по своему усмотрению.

Ответ 4

Для рабочего примера, который вам поможет, вы можете взглянуть на libcurl, библиотеку, написанную на языке C, которая

  • делает то, что вы хотите, и многое другое;

  • - это привязка к использованию;

  • широко используется; и

  • активно поддерживается.

Это прекрасная вещь и один из лучших примеров того, что open source может и должно быть.