真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何用socket發(fā)送http請求

如何用socket發(fā)送http請求,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

成都創(chuàng)新互聯(lián)2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元達拉特做網(wǎng)站,已為上家服務(wù),為達拉特各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

如何用socket發(fā)送http請求

平時我們使用瀏覽器瀏覽web資源,寫爬蟲的時候,我們會使用封裝好的庫,比如requests,或者使用爬蟲框架。工欲善其事必先利其器,頂層封裝好的東西,是為了我們使用著方便,節(jié)省開發(fā)時間,盡管各種http庫功能強大,但學(xué)習(xí)底層的技術(shù)仍然有著實踐意義,只有了解底層,才能真正理解頂層的封裝和設(shè)計,遇到那些艱難的問題時,才會有思路,有方案。  

1. 用socket發(fā)送http請求

瀏覽器也好,爬蟲框架也罷,在最底層,都是在使用socket發(fā)送http請求,然后接收服務(wù)端返回的數(shù)據(jù),瀏覽器會對返回的數(shù)據(jù)進行渲染,最終呈現(xiàn)在我們眼前,爬蟲框架相比于瀏覽器,只是少了一個渲染的過程。
用socket發(fā)送http請求,首先要建立一個TCP socket,然后連接到服務(wù)端socket,http請求的3次握手,本質(zhì)上是TCP socket建立連接的3次握手。連接建立好了以后,就要發(fā)送數(shù)據(jù)了,這里的數(shù)據(jù),可不是隨意發(fā)送的,而是要遵照http協(xié)議,下面的代碼,演示了socket發(fā)送http請求的過程
import socket


url = 'www.zhangdongshengtech.com'
port = 80

# 創(chuàng)建TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù)端
sock.connect((url, port))
# 創(chuàng)建請求消息頭
request_url = 'GET /article-types/6/ HTTP/1.1\r\nHost: www.zhangdongshengtech.com\r\nConnection: close\r\n\r\n'
print(request_url)
# 發(fā)送請求
sock.send(request_url.encode())
response = b''
# 接收返回的數(shù)據(jù)
rec = sock.recv(1024)
while rec:
   response += rec
   rec = sock.recv(1024)
print(response.decode())
代碼非常簡單,不做過多解釋,我們重點要了解的是http協(xié)議,request_url的內(nèi)容是
GET /article-types/6/ HTTP/1.1
Host: www.zhangdongshengtech.com
Connection: close
請求的消息頭,每一行都有各自的作用,在消息頭和消息體之間,有兩次換行,由于我們發(fā)送的是GET請求,沒有消息體,因此兩個換行后就結(jié)束了。
這3行,每一行都至關(guān)重要。
第一行的內(nèi)容,包含了三個重要信息
  1. GET 指明本次請求所使用的method,這是一次GET請求

  2. /article-types/6/ 指明了要請求的資源地址

  3. HTTP/1.1 指明http協(xié)議的版本,更早以前是1.0,現(xiàn)在大家都在用1.1

第二行的內(nèi)容,指明了host,一臺服務(wù)器上,也許不只是部署了一個web服務(wù),而是多個,他們都是80端口,url = 'www.zhangdongshengtech.com' 只是告訴socket去哪里建立連接,這僅僅是個域名而已,程序根據(jù)域名找到IP地址,如果服務(wù)端部署多個服務(wù),為了服務(wù)端區(qū)分一個請求是指向哪個服務(wù),客戶端需要在請求頭中指明host,服務(wù)端會根據(jù)這個host來做請求的轉(zhuǎn)發(fā),這就是常說的nginx反向代理。
第三行,定義了Connection的值是close,如果不定義,默認是keep-alive, 如果是keep-alive,那么服務(wù)端在返回數(shù)據(jù)后不會斷開連接,而是允許客戶端繼續(xù)使用這個連接發(fā)送請求,我故意設(shè)置成close,目的就是讓服務(wù)端主動斷開,這樣,當(dāng)程序在使用while循環(huán)時,接收完所有的數(shù)據(jù)后,sock.recv(1024) 返回的就是None,這樣,就可以停止程序了。如果是keep-alive,無法通過連接斷開來判斷數(shù)據(jù)是否已經(jīng)全部接收,那么就只能通過返回數(shù)據(jù)的消息頭來獲取數(shù)據(jù)的長度,進而決定本次請求返回的數(shù)據(jù)到哪里結(jié)束。

2. 返回的消息體

程序輸出了服務(wù)端返回的數(shù)據(jù),由于數(shù)據(jù)量很大,我們只截取消息頭的部分進行講解,消息體只是網(wǎng)頁源碼而已,沒什么可說的。
HTTP/1.1 200 OK
Server: openresty/1.11.2.1
Date: Sun, 05 May 2019 03:11:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 29492
Connection: close
Set-Cookie: session=eyJjc3JmX3Rva2VuIjp7IiBiIjoiTn
prd1pqZGhaamd6T1dObFlUQTRZVFJqTkRJeU9USmtNalU0TldOaU1UQXdNamsxTkdSaVpRPT0ifX0.D6_lyQ.
4EqkK8taszUkPtMsol-8pzF_LQM; HttpOnly; Path=/




返回的數(shù)據(jù)中,消息頭和消息體之間,也是兩個換行。
第一行,HTTP/1.1 200 OK 指明了http協(xié)議的版本,已經(jīng)本次請求返回的狀態(tài)碼,200表示成功響應(yīng),比較常見的還有404,500,302,這些狀態(tài)碼的含義,你可以自己百度一下。
第二行開始的消息頭內(nèi)容中,比較重要的是Content-Length,它的值是29492,這表明,消息體的長度是29492,如果Connection的值是keep-alive,客戶端就得根據(jù)這個值來讀取消息體。
請求的消息體和服務(wù)端響應(yīng)的消息體中,除了第一行外,其他的長的很像字典形式的key-value對,叫首部,本文只涉及到個別幾個首部,其他首部及其含義,你可以自行百度。

3. 從消息頭解析出content_length

增加一點難度,從消息頭里獲取content_length,在獲取返回數(shù)據(jù)時,當(dāng)消息體的長度滿足要求時,停止獲取數(shù)據(jù),并關(guān)閉連接
import socket


url = 'www.zhangdongshengtech.com'
port = 80
# 創(chuàng)建TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù)端
sock.connect((url, port))
# 創(chuàng)建請求消息頭
request_url = 'GET /article-types/6/ HTTP/1.1\r\nHost: www.zhangdongshengtech.com\r\n\r\n'
print(request_url)
# 發(fā)送請求
sock.send(request_url.encode())
body = ''
# 接收返回的數(shù)據(jù)
rec = sock.recv(1024)


index = rec.find(b'\r\n\r\n')       # 找到消息頭與消息體分割的地方
head = rec[:index]
body = rec[index+4:]

# 獲取Content-Length
headers = head.split(b'\r\n')
for header in headers:
   if header.startswith(b'Content-Length'):
       content_length = int(header.split(b' ')[1])

length = len(body)

while length < content_length:
   rec = sock.recv(1024)
   length += len(rec)
   body += rec

sock.close()
print(length)
print(head.decode())
print(body.decode())

關(guān)于如何用socket發(fā)送http請求問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。


當(dāng)前題目:如何用socket發(fā)送http請求
分享地址:http://weahome.cn/article/iihojs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部