【前後端交互】-幾個問題及答案
為了實現一次最簡單的前後端交互,手寫了一個tcp_socket作為後台,綁定本地127.0.0.1+80 ,GET請求會返回一個html頁面。客戶端用的360瀏覽器。
解決了幾個問題,解決問題的過程也是糾正理解的過程。
問題1:瀏覽器第一次發出GET請求可以成功拿到頁面,但是點提交,後台的接收一直阻塞,收不到數據。直至關閉瀏覽器,在後台才能看到之前請求的數據。
原因:瀏覽器發送GET請求,用一個埠;第二次提交時,用post提交表單,換了另一個埠。而當前socket不支持並發,一次只能建立一個會話,因此……
問題2:瀏覽器get請求到頁面,關閉以後,服務端會進入「收空」的死循環
原因:寫socket的時候一開始沒考慮好,如果client主動斷開連接,會怎麼樣?
在之前客戶端也是socket的例子中,一旦發生這種情況,conn就不存在了,會發生異常,所以用try-except:breakt來終結。但是,沒想到的是,當客戶端換成瀏覽器,conn還在,只是data一直為空,伺服器端也不再阻塞。這個現象的原因在這裡:
所以這個時候不斷拿到空字元並不是因為客戶端真的在發,而是服務端自己的一個特性,或者說措施,提醒你客戶端已經斷開了,該改變啦
這時異常處理不起作用,就需要另外來一個if not data:break。
問題3:<form>標籤enctype屬性取值,與提交數據的格式問題有關
<form action="http://127.0.0.1/80" method="POST" enctype="application/x-www-form-urlencoded">
enctype 屬性規定在發送到伺服器之前應該如何對錶單數據進行編碼。
默認也是enctype="application/x-www-form-urlencoded",此時表單數據會編碼為 "application/x-www-form-urlencoded(content-type)"。就是說,在發送到伺服器之前,所有字元都會進行編碼(空格轉換為 "+" 加號,特殊符號轉換為 ASCII HEX 值)。
另外的取值還有:
在默認情況下,實際發出去的表單是經過編碼的,長這樣:
這個表單時原始數據經過URL編碼產生的。
然後點view parsed可以還原真實的數據,是這樣:
再點view URL encoded,看到原始數據被編碼以後(空格變這樣),是這樣
如果令enctype="multipart/form-data",將會看到不一樣的表單格式:
附:tcp_socket_server.py
from socket import *s=socket(AF_INET,SOCK_STREAM)s.bind((127.0.0.1,80))s.listen(5)#5是backlog的數量,最大建立5個連接,除了當前的其他在後台掛起print(tcp_server:listening……)while True: #接收一個新的conn,可能該conn已經在後台就等了 conn,addr=s.accept() print(accpet an new connection,with conn={0}。addr={1}.format(conn,addr)) while True: try: data_recv=conn.recv(1024) if not data_recv: break if (isinstance(data_recv, bytes)): print(len(data_recv)) data_recv=data_recv.decode(utf-8) print(type(data_recv)) print(1+data_recv) if data_recv.startswith(GET): f=open("html_practicing/params.html",rb) conn.send(f.read()) print(已經響應GET請求) elif data_recv.startswith(POST): #print(data_recv.encode(utf-8)) conn.send(1234.encode(utf-8)) print(已經響應POST請求) except Exception as e: print(e) print(exception,go to accpet next ) #主要客戶端主動斷開連接,當前conn不見了,就會異常,這時我們的處理是直接跳出內層while #用break而不是continue,表示不是跳出這一輪開始下一輪,而是徹底結束整個循環 break #conn.close()#這一句不執行也沒事,因為外層while開頭總是會給conn賦新的值,而原有conn看print(conn)還有相關信息,但netstat -an查看已經沒有了。大概理解為這個連接已經失效了,但還保持相關信息,但調用會出錯。 print(conn.close被執行)s.close()#在於客戶端1234全部會話完成後,讓s進程關閉,雖然實際應該不是這樣……
推薦閱讀:
※實現單行文字兩端對齊時,使用 當作空格和使用 white-space: pre 的原生空格有什麼區別?哪個更好一些?
※瀏覽器文件緩存和304的區別?
※Debug前端HTML/CSS
※web應用使用jsp還是html做前端頁面?
TAG:HTML |