socket模擬發送http請求

socket模擬發送http請求

嗨,小夥伴們,好久不見~~~,最近博主在研究socket編程,覺得socket真的好強大。之前一直我們都是在介紹爬蟲的requests、urllib等庫,我們知道它們都是基於HTTP協議來實現的,但從來沒有講過這個是如何實現的。今天要是講的話,一時半會也說不清楚,最重要的是,我怕自己講不明白。這樣大家就變的更糊塗,所以我就不講了。今天要說的是如何基於socket來發送http請求。

大家都知道,osi有七層模型,但是我們的TCP/IP協議其實並不是完全符合這個模型的。但是有些東西兩者都具有的,我們這裏簡要說一下傳輸層和應用層。

我們知道這個傳輸層是TCP和UTP協議,應用層則是我們經常使用的HTTP、SMTP、FTP等協議。應用層的那些協議都是基於傳輸層協議來的,都是爲了實現特定的功能而進行封裝的。那麼大家就要問了,這個socket是什麼,在哪裏呢?往下看:

原來在這裏啊,Socket它是應用層與傳輸層(TCP/IP協議族)通信的中間軟件抽象層,我們可以認爲它是一組接口(api)。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。我們可以利用Socket來模擬HTTP請求,從而實現僞HTTP協議的目的。

我們以get方式來請求百度首頁爲例,利用Socket來模擬發送HTTP請求。

我們可以直接仿照瀏覽器的請求頭部信息去發送請求,當然也可以通過urllib提供的urlparse方法來對url進行修改,然後通過傳遞參數的方式來發送信息,相關的代碼如下:

# /usr/bin/python
# -*- coding:utf-8 -*-
# @author: Envse
# @file: socket_http.py
# @time: 2018/10/03 16:06


# requests -->urllib -->socket
import socket
from urllib.parse import urlparse


def get_url(url):
    # 通過socket請求Url
    url = urlparse(url)
    host = url.netloc
    path = url.path
    if path == "":
        path = "/"

    # 建立socket連接
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((host, 80))

    client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode('utf8'))# 相對路徑
    data = b""
    while True:
        d = client.recv(1024)
        if d:
            data += d
        else:
            break

    data = data.decode('utf8')
    html_data = data.split("\r\n\r\n")[1]
    print(html_data)
    client.close()


if __name__ == '__main__':
    get_url("http://www.baidu.com/")

這段代碼其實很好理解,就是模擬客戶端向服務器發送請求。首先通過get_url方法來將我們需要模擬的url進行處理,然後建立socket連接,發送內容,最後接收響應內容並將其進行輸出,關閉連接,是不是很簡單呢。運行結果:

再來看看通過瀏覽器查看的百度首頁的源碼,是不是差不多:

之所以出現有些差別是因爲瀏覽器是基於HTTP協議的,而且進行了一些字更深層次的封裝。不知道今年這篇文章您看明白沒有,如果沒有,我哪天再來研究一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章