龙空技术网

Python中requests获取网络请求背后的socket

洪较瘦不着调退役it人 358

前言:

此刻姐妹们对“python发送socket请求”都比较注意,姐妹们都需要分析一些“python发送socket请求”的相关知识。那么小编同时在网摘上汇集了一些有关“python发送socket请求””的相关内容,希望大家能喜欢,大家一起来了解一下吧!

这是我们访问一个网站的大概逻辑截图

图片来源网络

当我们在浏览器中输入某个网址如baiducom回车后,计算机会把这个请求HTTP发送出来,当然最后的信息都是物理上的,在更高层面的网络应用协议上则是HTTP协议

HTTP协议的本质是一路有规范的文本,可以看下面的这一段内容就是一下简单的HTTP协议

POST /api/user HTTP/1.1Host: example.comContent-Type: application/jsonContent-Length: 45{"username": "john", "password": "secretpassword"} 

前面我们使用requests来实现网页或者网络请求的数据获取如下:

rimport requestses = requests.get(        f'{city}&oq={city}&aqs=chrome.0.35i39l2j0l4j46j69i60.6128j1j7&sourceid=chrome&ie=UTF-8', headers=headers)    print("Searching...\n")

但是在这个代码中并没有看到发着HTTP协议 的内容。

Socket

我们上网的时候,的服务器会有一个IP地址,我们的电脑通过DNS找到侬个地址后会向淘宝的电脑80端口发送HTTP协议的数据,端口可以理解一个屋子的窗户,它只处理指定格格式的数据。

这进我们的电脑浏览器客户端本地分配一个动态端口来与淘宝服务器进行数据交换,这样的一组ipport的信息就构成了一个socket的构成部分socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

Socket其实为我们连接计算机网络中的一种通信机制,它与TCP/IP解决的是不同层面 的问题。

网上图片

request是如何使用socket的

def get(url, params=None, **kwargs)    return request("get", url, params=params, **kwargs)

看一下request的方法

class Session(SessionRedirectMixin):    def __init__(self):        self.headers = default_headers()        self.auth = None        self.proxies = {        self.mount(';, HTTPAdapter())        self.mount(';, HTTPAdapter())    def __enter__(self):        return self    def __exit__(self, *args):        self.close()    def prepare_request(self, request):                cookies = request.cookies or {}        p = PreparedRequest()        p.prepare(                  )        return p    def request(self, method, url,            params=None, data=None, headers=None, cookies=None, files=None,            auth=None, timeout=None, allow_redirects=True, proxies=None,            hooks=None, stream=None, verify=None, cert=None, json=None):               # Create the Request.        req = Request(            method=method.upper(),        )        settings = self.merge_environment_settings(            prep.url, proxies, stream, verify, cert        )        # Send the request.        send_kwargs = {            'timeout': timeout,            'allow_redirects': allow_redirects,        }        send_kwargs.update(settings)        resp = self.send(prep, **send_kwargs)        return resp    def get(self, url, **kwargs):        kwargs.setdefault('allow_redirects', True)        return self.request('GET', url, **kwargs)

在哪里发送请求resp = self.send(prep, **send_kwargs)

        send_kwargs = {            'timeout': timeout,            'allow_redirects': allow_redirects,        }        send_kwargs.update(settings)        resp = self.send(prep, **send_kwargs)        return resp

经过Session-->HTTPAdapter--> HTTPConnection 这一串类的查找我们最后发现了这样一个方法

def _new_conn(self):        """Establish a socket connection and set nodelay settings on it.        :return: New socket connection.        """        extra_kw = {}        if self.source_address:            extra_kw["source_address"] = self.source_address        if self.socket_options:            extra_kw["socket_options"] = self.socket_options        try:            conn = connection.create_connection(                (self._dns_host, self.port), self.timeout, **extra_kw            )

最终一个所谓的HTTPconnection对应提一个socket

def create_connection(    address,    timeout=socket._GLOBAL_DEFAULT_TIMEOUT,    source_address=None,    socket_options=None,):    host, port = address    try:        host.encode("idna")    except UnicodeError:        return six.raise_from(            LocationParseError(u"'%s', label empty or too long" % host), None        )    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):        af, socktype, proto, canonname, sa = res        sock = None        try:            sock = socket.socket(af, socktype, proto)            # If provided, set socket level options before connecting.            _set_socket_options(sock, socket_options)            if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:                sock.settimeout(timeout)            if source_address:                sock.bind(source_address)            sock.connect(sa)            return sock        except socket.error as e:            err = e            if sock is not None:                sock.close()                sock = None 

可以看到Socket是如何创建的

 for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):        af, socktype, proto, canonname, sa = res        sock = None        try:            sock = socket.socket(af, socktype, proto) 

所以发送http协议还是依旧使用的是socket编程接口

socket的使用确定目标主机和端口连接这个目标主机端口,发送数据,接收目标主机的返回数据

我们使用socket来获取百度的页面数据

    import sockettarget_host = "; target_port = 80  # create a socket object client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # connect the client client.connect((target_host,target_port))  # send some data request = "GET / HTTP/1.1\r\nHost:%s\r\n\r\n" % target_hostprint(request)client.send(request.encode())  # receive some data while 1:    response = client.recv(4096)    if response:        # print(type(response))        http_response =  response.decode()        http_response_len = len(http_response)        print(http_response)

可以看到返回的内容如下:

标签: #python发送socket请求