日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

网络编程学习

發(fā)布時(shí)間:2024/3/26 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

python高級(jí)——IP 地址的介紹

  • IP 地址的作用
      • 1. IP 地址的概念
      • 2. IP 地址的表現(xiàn)形式
      • 3. IP 地址的作用
      • 4. 查看 IP 地址
      • 5檢查網(wǎng)絡(luò)是否正常
  • TCP 的介紹
    • 1. 網(wǎng)絡(luò)應(yīng)用程序之間的通信流程
    • 2. TCP 的概念
    • 3. TCP 的特點(diǎn)
    • 4. 總結(jié)
  • socket 的介紹
    • socket 的作用
    • socket 使用場(chǎng)景
  • TCP 網(wǎng)絡(luò)應(yīng)用程序開發(fā)流程的介紹
  • TCP 客戶端程序開發(fā)流程的介紹
    • 開發(fā) TCP 客戶端程序開發(fā)步驟:
    • socket 類的介紹
    • TCP 客戶端程序開發(fā)示例代碼
    • 小結(jié)
  • TCP 服務(wù)端程序開發(fā)流程的介紹
    • socket 類的介紹
    • TCP 服務(wù)端程序開發(fā)示例代碼
    • 小結(jié)
  • TCP網(wǎng)絡(luò)應(yīng)用程序的注意點(diǎn)
  • socket之send和recv原理剖析
    • 認(rèn)識(shí)TCP socket的發(fā)送和接收緩沖區(qū)
    • send原理剖析
    • recv原理剖析
    • send和recv原理剖析圖
  • URL
    • HTTP 請(qǐng)求報(bào)文
    • HTTP響應(yīng)報(bào)文
    • 搭建Python自帶靜態(tài)Web服務(wù)器
    • 靜態(tài)Web服務(wù)器-返回固定頁(yè)面數(shù)據(jù)
    • 靜態(tài)Web服務(wù)器-返回指定頁(yè)面數(shù)據(jù)
    • 靜態(tài)Web服務(wù)器-多任務(wù)版
    • 靜態(tài)Web服務(wù)器-面向?qū)ο箝_發(fā)
    • 靜態(tài)Web服務(wù)器-命令行啟動(dòng)動(dòng)態(tài)綁定端口號(hào)

IP 地址的作用

1. IP 地址的概念

IP 地址就是標(biāo)識(shí)網(wǎng)絡(luò)中設(shè)備的一個(gè)地址,好比現(xiàn)實(shí)生活中的家庭地址。
網(wǎng)絡(luò)中的設(shè)備效果圖:

2. IP 地址的表現(xiàn)形式

IP 地址分為兩類: IPv4 和 IPv6

IPv4 是目前使用的ip地址

IPv6 是未來使用的ip地址

IPv4 是由點(diǎn)分十進(jìn)制組成

IPv6 是由冒號(hào)十六進(jìn)制組成

3. IP 地址的作用

IP 地址的作用是標(biāo)識(shí)網(wǎng)絡(luò)中唯一的一臺(tái)設(shè)備的,也就是說通過IP地址能夠找到網(wǎng)絡(luò)中某臺(tái)設(shè)備。

4. 查看 IP 地址

Linux 和 mac OS 使用 ifconfig 這個(gè)命令
Windows 使用 ipconfig 這個(gè)命令
說明:
ifconfig 和 ipconfig 都是查看網(wǎng)卡信息的,網(wǎng)卡信息中包括這個(gè)設(shè)備對(duì)應(yīng)的IP地址
說明:
192.168.1.107是設(shè)備在網(wǎng)絡(luò)中的IP地址
127.0.0.1表示本機(jī)地址,提示:如果和自己的電腦通信就可以使用該地址。
127.0.0.1該地址對(duì)應(yīng)的域名是localhost,域名是 ip 地址的別名,通過域名能解析出一個(gè)對(duì)應(yīng)的ip地址。

5檢查網(wǎng)絡(luò)是否正常

檢查網(wǎng)絡(luò)是否正常使用 ping 命令
說明:
ping www.baidu.com 檢查是否能上公網(wǎng)
ping 當(dāng)前局域網(wǎng)的ip地址 檢查是否在同一個(gè)局域網(wǎng)內(nèi)
ping 127.0.0.1 檢查本地網(wǎng)卡是否正常
IP 地址的作用是標(biāo)識(shí)網(wǎng)絡(luò)中唯一的一臺(tái)設(shè)備的
IP 地址的表現(xiàn)形式分為: IPv4 和 IPv6
查看網(wǎng)卡信息:ifconfig
檢查網(wǎng)絡(luò): ping

TCP 的介紹

1. 網(wǎng)絡(luò)應(yīng)用程序之間的通信流程

通過 IP 地址能夠找到對(duì)應(yīng)的設(shè)備,然后再通過端口號(hào)找到對(duì)應(yīng)的端口,再通過端口把數(shù)據(jù)傳輸給應(yīng)用程序,這里要注意,數(shù)據(jù)不能隨便發(fā)送,在發(fā)送之前還需要選擇一個(gè)對(duì)應(yīng)的傳輸協(xié)議,保證程序之間按照指定的傳輸規(guī)則進(jìn)行數(shù)據(jù)的通信, 而這個(gè)傳輸協(xié)議就是我們今天學(xué)習(xí)的 TCP。

2. TCP 的概念

TCP 的英文全拼(Transmission Control Protocol)簡(jiǎn)稱傳輸控制協(xié)議,它是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
TCP 通信步驟:

創(chuàng)建連接
傳輸數(shù)據(jù)
關(guān)閉連接
說明:

TCP 通信模型相當(dāng)于生活中的’打電話‘,在通信開始之前,一定要先建立好連接,才能發(fā)送數(shù)據(jù),通信結(jié)束要關(guān)閉連接。

3. TCP 的特點(diǎn)

面向連接
通信雙方必須先建立好連接才能進(jìn)行數(shù)據(jù)的傳輸,數(shù)據(jù)傳輸完成后,雙方必須斷開此連接,以釋放系統(tǒng)資源。
可靠傳輸
TCP 采用發(fā)送應(yīng)答機(jī)制
超時(shí)重傳
錯(cuò)誤校驗(yàn)
流量控制和阻塞管理

4. 總結(jié)

TCP 是一個(gè)穩(wěn)定、可靠的傳輸協(xié)議,常用于對(duì)數(shù)據(jù)進(jìn)行準(zhǔn)確無誤的傳輸,比如: 文件下載,瀏覽器上網(wǎng)。

socket 的介紹

socket 的概念
socket (簡(jiǎn)稱 套接字) 是進(jìn)程之間通信一個(gè)工具,好比現(xiàn)實(shí)生活中的插座,所有的家用電器要想工作都是基于插座進(jìn)行,進(jìn)程之間想要進(jìn)行網(wǎng)絡(luò)通信需要基于這個(gè) socket。

socket 的作用

負(fù)責(zé)進(jìn)程之間的網(wǎng)絡(luò)數(shù)據(jù)傳輸,好比數(shù)據(jù)的搬運(yùn)工。

socket 使用場(chǎng)景

不夸張的說,只要跟網(wǎng)絡(luò)相關(guān)的應(yīng)用程序或者軟件都使用到了 socket 。
進(jìn)程之間網(wǎng)絡(luò)數(shù)據(jù)的傳輸可以通過 socket 來完成, socket 就是進(jìn)程間網(wǎng)絡(luò)數(shù)據(jù)通信的工具。

TCP 網(wǎng)絡(luò)應(yīng)用程序開發(fā)流程的介紹

TCP 網(wǎng)絡(luò)應(yīng)用程序開發(fā)分為:
TCP 客戶端程序開發(fā)
TCP 服務(wù)端程序開發(fā)
說明:
客戶端程序是指運(yùn)行在用戶設(shè)備上的程序 服務(wù)端程序是指運(yùn)行在服務(wù)器設(shè)備上的程序,專門為客戶端提供數(shù)據(jù)服務(wù)。

TCP 客戶端程序開發(fā)流程的介紹

開發(fā) TCP 客戶端程序開發(fā)步驟:

創(chuàng)建客戶端套接字對(duì)象
和服務(wù)端套接字建立連接
發(fā)送數(shù)據(jù)
接收數(shù)據(jù)
關(guān)閉客戶端套接字

socket 類的介紹

導(dǎo)入 socket 模塊 import socket

創(chuàng)建客戶端 socket 對(duì)象 socket.socket(AddressFamily, Type)

參數(shù)說明:

AddressFamily 表示IP地址類型, 分為TPv4和IPv6
Type 表示傳輸協(xié)議類型
方法說明:

connect((host, port)) 表示和服務(wù)端套接字建立連接, host是服務(wù)器ip地址,port是應(yīng)用程序的端口號(hào)
send(data) 表示發(fā)送數(shù)據(jù),data是二進(jìn)制數(shù)據(jù)
recv(buffersize) 表示接收數(shù)據(jù), buffersize是每次接收數(shù)據(jù)的長(zhǎng)度

TCP 客戶端程序開發(fā)示例代碼

import socket if __name__ == '__main__':# 創(chuàng)建tcp客戶端套接字# 1. AF_INET:表示ipv4# 2. SOCK_STREAM: tcp傳輸協(xié)議tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 和服務(wù)端應(yīng)用程序建立連接tcp_client_socket.connect(("192.168.131.62", 8080))# 代碼執(zhí)行到此,說明連接建立成功# 準(zhǔn)備發(fā)送的數(shù)據(jù)send_data = "你好服務(wù)端,我是客戶端小黑!".encode("gbk")# 發(fā)送數(shù)據(jù)tcp_client_socket.send(send_data)# 接收數(shù)據(jù), 這次接收的數(shù)據(jù)最大字節(jié)數(shù)是1024recv_data = tcp_client_socket.recv(1024)# 返回的直接是服務(wù)端程序發(fā)送的二進(jìn)制數(shù)據(jù)print(recv_data)# 對(duì)數(shù)據(jù)進(jìn)行解碼recv_content = recv_data.decode("gbk")print("接收服務(wù)端的數(shù)據(jù)為:", recv_content)# 關(guān)閉套接字tcp_client_socket.close() #執(zhí)行結(jié)果:#b'hello' #接收服務(wù)端的數(shù)據(jù)為: hello #說明#str.encode(編碼格式) 表示把字符串編碼成為二進(jìn)制 #data.decode(編碼格式) 表示把二進(jìn)制解碼成為字符串

小結(jié)

導(dǎo)入socket模塊
創(chuàng)建TCP套接字‘socket’
參數(shù)1: ‘AF_INET’, 表示IPv4地址類型
參數(shù)2: ‘SOCK_STREAM’, 表示TCP傳輸協(xié)議類型
發(fā)送數(shù)據(jù)‘send’
參數(shù)1: 要發(fā)送的二進(jìn)制數(shù)據(jù), 注意: 字符串需要使用encode()方法進(jìn)行編碼
接收數(shù)據(jù)‘recv’
參數(shù)1: 表示每次接收數(shù)據(jù)的大小,單位是字節(jié)
關(guān)閉套接字‘socket’表示通信完成

TCP 服務(wù)端程序開發(fā)流程的介紹

socket 類的介紹

導(dǎo)入 socket 模塊
import socket

創(chuàng)建服務(wù)端 socket 對(duì)象
socket.socket(AddressFamily, Type)

參數(shù)說明:

AddressFamily 表示IP地址類型, 分為TPv4和IPv6
Type 表示傳輸協(xié)議類型
方法說明:

bind((host, port)) 表示綁定端口號(hào), host 是 ip 地址,port 是端口號(hào),ip 地址一般不指定,表示本機(jī)的任何一個(gè)ip地址都可以。
listen (backlog) 表示設(shè)置監(jiān)聽,backlog參數(shù)表示最大等待建立連接的個(gè)數(shù)。
accept() 表示等待接受客戶端的連接請(qǐng)求
send(data) 表示發(fā)送數(shù)據(jù),data 是二進(jìn)制數(shù)據(jù)
recv(buffersize) 表示接收數(shù)據(jù), buffersize 是每次接收數(shù)據(jù)的長(zhǎng)度

TCP 服務(wù)端程序開發(fā)示例代碼

import socketif __name__ == '__main__':# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用,讓程序退出端口號(hào)立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 給程序綁定端口號(hào)tcp_server_socket.bind(("", 8989))# 設(shè)置監(jiān)聽# 128:最大等待建立連接的個(gè)數(shù), 提示: 目前是單任務(wù)的服務(wù)端,同一時(shí)刻只能服務(wù)與一個(gè)客戶端,后續(xù)使用多任務(wù)能夠讓服務(wù)端同時(shí)服務(wù)與多個(gè)客戶端,# 不需要讓客戶端進(jìn)行等待建立連接# listen后的這個(gè)套接字只負(fù)責(zé)接收客戶端連接請(qǐng)求,不能收發(fā)消息,收發(fā)消息使用返回的這個(gè)新套接字來完成tcp_server_socket.listen(128)# 等待客戶端建立連接的請(qǐng)求, 只有客戶端和服務(wù)端建立連接成功代碼才會(huì)解阻塞,代碼才能繼續(xù)往下執(zhí)行# 1. 專門和客戶端通信的套接字: service_client_socket# 2. 客戶端的ip地址和端口號(hào): ip_portservice_client_socket, ip_port = tcp_server_socket.accept()# 代碼執(zhí)行到此說明連接建立成功print("客戶端的ip地址和端口號(hào):", ip_port)# 接收客戶端發(fā)送的數(shù)據(jù), 這次接收數(shù)據(jù)的最大字節(jié)數(shù)是1024recv_data = service_client_socket.recv(1024)# 獲取數(shù)據(jù)的長(zhǎng)度recv_data_length = len(recv_data)print("接收數(shù)據(jù)的長(zhǎng)度為:", recv_data_length)# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_content = recv_data.decode("gbk")print("接收客戶端的數(shù)據(jù)為:", recv_content)# 準(zhǔn)備發(fā)送的數(shù)據(jù)send_data = "ok, 問題正在處理中...".encode("gbk")# 發(fā)送數(shù)據(jù)給客戶端service_client_socket.send(send_data)# 關(guān)閉服務(wù)與客戶端的套接字, 終止和客戶端通信的服務(wù)service_client_socket.close()# 關(guān)閉服務(wù)端的套接字, 終止和客戶端提供建立連接請(qǐng)求的服務(wù)tcp_server_socket.close() #執(zhí)行結(jié)果:#客戶端的ip地址和端口號(hào): ('172.16.47.209', 52472) #接收數(shù)據(jù)的長(zhǎng)度為: 5 #接收客戶端的數(shù)據(jù)為: hello #說明:#當(dāng)客戶端和服務(wù)端建立連接后,服務(wù)端程序退出后端口號(hào)不會(huì)立即釋放,需要等待大概1-2分鐘。

解決辦法有兩種:

更換服務(wù)端端口號(hào)
設(shè)置端口號(hào)復(fù)用(推薦大家使用),也就是說讓服務(wù)端程序退出后端口號(hào)立即釋放。
設(shè)置端口號(hào)復(fù)用的代碼如下:

參數(shù)1: 表示當(dāng)前套接字
參數(shù)2: 設(shè)置端口號(hào)復(fù)用選項(xiàng)
參數(shù)3: 設(shè)置端口號(hào)復(fù)用選項(xiàng)對(duì)應(yīng)的值
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

小結(jié)

導(dǎo)入socket模塊
創(chuàng)建TCP套接字‘socket’
參數(shù)1: ‘AF_INET’, 表示IPv4地址類型
參數(shù)2: ‘SOCK_STREAM’, 表示TCP傳輸協(xié)議類型
綁定端口號(hào)‘bind’
參數(shù): 元組, 比如:(ip地址, 端口號(hào))
設(shè)置監(jiān)聽‘listen’
參數(shù): 最大等待建立連接的個(gè)數(shù)
等待接受客戶端的連接請(qǐng)求‘a(chǎn)ccept’
發(fā)送數(shù)據(jù)‘send’
參數(shù): 要發(fā)送的二進(jìn)制數(shù)據(jù), 注意: 字符串需要使用encode()方法進(jìn)行編碼
接收數(shù)據(jù)‘recv’
參數(shù): 表示每次接收數(shù)據(jù)的大小,單位是字節(jié),注意: 解碼成字符串使用decode()方法
關(guān)閉套接字‘socket’表示通信完成

TCP網(wǎng)絡(luò)應(yīng)用程序的注意點(diǎn)

TCP網(wǎng)絡(luò)應(yīng)用程序的注意點(diǎn)介紹
當(dāng) TCP 客戶端程序想要和 TCP 服務(wù)端程序進(jìn)行通信的時(shí)候必須要先建立連接
TCP 客戶端程序一般不需要綁定端口號(hào),因?yàn)榭蛻舳耸侵鲃?dòng)發(fā)起建立連接的。
TCP 服務(wù)端程序必須綁定端口號(hào),否則客戶端找不到這個(gè) TCP 服務(wù)端程序。
listen 后的套接字是被動(dòng)套接字,只負(fù)責(zé)接收新的客戶端的連接請(qǐng)求,不能收發(fā)消息。
當(dāng) TCP 客戶端程序和 TCP 服務(wù)端程序連接成功后, TCP 服務(wù)器端程序會(huì)產(chǎn)生一個(gè)新的套接字,收發(fā)客戶端消息使用該套接字。
關(guān)閉 accept 返回的套接字意味著和這個(gè)客戶端已經(jīng)通信完畢。
關(guān)閉 listen 后的套接字意味著服務(wù)端的套接字關(guān)閉了,會(huì)導(dǎo)致新的客戶端不能連接服務(wù)端,但是之前已經(jīng)接成功的客戶端還能正常通信。
當(dāng)客戶端的套接字調(diào)用 close 后,服務(wù)器端的 recv 會(huì)解阻塞,返回的數(shù)據(jù)長(zhǎng)度為0,服務(wù)端可以通過返回?cái)?shù)據(jù)的長(zhǎng)度來判斷客戶端是否已經(jīng)下線,反之服務(wù)端關(guān)閉套接字,客戶端的 recv 也會(huì)解阻塞,返回的數(shù)據(jù)長(zhǎng)度也為0。

socket之send和recv原理剖析

認(rèn)識(shí)TCP socket的發(fā)送和接收緩沖區(qū)

當(dāng)創(chuàng)建一個(gè)TCP socket對(duì)象的時(shí)候會(huì)有一個(gè)發(fā)送緩沖區(qū)和一個(gè)接收緩沖區(qū),這個(gè)發(fā)送和接收緩沖區(qū)指的就是內(nèi)存中的一片空間。

send原理剖析

send是不是直接把數(shù)據(jù)發(fā)給服務(wù)端?
不是,要想發(fā)數(shù)據(jù),必須得通過網(wǎng)卡發(fā)送數(shù)據(jù),應(yīng)用程序是無法直接通過網(wǎng)卡發(fā)送數(shù)據(jù)的,它需要調(diào)用操作系統(tǒng)接口,也就是說,應(yīng)用程序把發(fā)送的數(shù)據(jù)先寫入到發(fā)送緩沖區(qū)(內(nèi)存中的一片空間),再由操作系統(tǒng)控制網(wǎng)卡把發(fā)送緩沖區(qū)的數(shù)據(jù)發(fā)送給服務(wù)端網(wǎng)卡 。

recv原理剖析

recv是不是直接從客戶端接收數(shù)據(jù)?
不是,應(yīng)用軟件是無法直接通過網(wǎng)卡接收數(shù)據(jù)的,它需要調(diào)用操作系統(tǒng)接口,由操作系統(tǒng)通過網(wǎng)卡接收數(shù)據(jù),把接收的數(shù)據(jù)寫入到接收緩沖區(qū)(內(nèi)存中的一片空間),應(yīng)用程序再?gòu)慕邮站彺鎱^(qū)獲取客戶端發(fā)送的數(shù)據(jù)。

send和recv原理剖析圖


說明:
發(fā)送數(shù)據(jù)是發(fā)送到發(fā)送緩沖區(qū)
接收數(shù)據(jù)是從接收緩沖區(qū) 獲取
不管是recv還是send都不是直接接收到對(duì)方的數(shù)據(jù)和發(fā)送數(shù)據(jù)到對(duì)方,發(fā)送數(shù)據(jù)會(huì)寫入到發(fā)送緩沖區(qū),接收數(shù)據(jù)是從接收緩沖區(qū)來讀取,發(fā)送數(shù)據(jù)和接收數(shù)據(jù)最終是由操作系統(tǒng)控制網(wǎng)卡來完成。

URL

URL的概念

URL的英文全拼是(Uniform Resoure Locator),表達(dá)的意思是統(tǒng)一資源定位符,通俗理解就是網(wǎng)絡(luò)資源地址,也就是我們常說的網(wǎng)址。
URL的組成部分:
協(xié)議部分: https://、http://、ftp://
域名部分: news.163.com
資源路徑部分: /18/1122/10/E178J2O4000189FH.html
域名:域名就是IP地址的別名,它是用點(diǎn)進(jìn)行分割使用英文字母和數(shù)字組成的名字,使用域名目的就是方便的記住某臺(tái)主機(jī)IP地址。

HTTP 請(qǐng)求報(bào)文

HTTP最常見的請(qǐng)求報(bào)文有兩種:
GET 方式的請(qǐng)求報(bào)文 GET: 獲取web服務(wù)器數(shù)據(jù)
POST 方式的請(qǐng)求報(bào)文 POST: 向web服務(wù)器提交數(shù)據(jù)
一個(gè)HTTP請(qǐng)求報(bào)文可以由請(qǐng)求行、請(qǐng)求頭、空行和請(qǐng)求體4個(gè)部分組成。
請(qǐng)求行是由三部分組成:
請(qǐng)求方式
請(qǐng)求資源路徑
HTTP協(xié)議版本
GET方式的請(qǐng)求報(bào)文沒有請(qǐng)求體,只有請(qǐng)求行、請(qǐng)求頭、空行組成。
POST方式的請(qǐng)求報(bào)文可以有請(qǐng)求行、請(qǐng)求頭、空行、請(qǐng)求體四部分組成,注意:POST方式可以允許沒有請(qǐng)求體,但是這種格式很少見

HTTP響應(yīng)報(bào)文

HTTP 狀態(tài)碼是用于表示web服務(wù)器響應(yīng)狀態(tài)的3位數(shù)字代碼。
狀態(tài)碼 說明
200 請(qǐng)求成功
307 重定向
400 錯(cuò)誤的請(qǐng)求,請(qǐng)求地址或者參數(shù)有誤
404 請(qǐng)求資源在服務(wù)器不存在
500 服務(wù)器內(nèi)部源代碼出現(xiàn)錯(cuò)誤
一個(gè)HTTP響應(yīng)報(bào)文是由響應(yīng)行、響應(yīng)頭、空行和響應(yīng)體4個(gè)部分組成。
響應(yīng)行是由三部分組成:HTTP協(xié)議版本 狀態(tài)碼 狀態(tài)描述,最常見的狀態(tài)碼是200

搭建Python自帶靜態(tài)Web服務(wù)器

靜態(tài)Web服務(wù)器是什么?
可以為發(fā)出請(qǐng)求的瀏覽器提供靜態(tài)文檔的程序。
平時(shí)我們?yōu)g覽百度新聞數(shù)據(jù)的時(shí)候,每天的新聞數(shù)據(jù)都會(huì)發(fā)生變化,那訪問的這個(gè)頁(yè)面就是動(dòng)態(tài)的,而我們開發(fā)的是靜態(tài)的,頁(yè)面的數(shù)據(jù)不會(huì)發(fā)生變化。
如何搭建Python自帶的靜態(tài)Web服務(wù)器
搭建Python自帶的靜態(tài)Web服務(wù)器使用 python3 -m http.server 端口號(hào)
m選項(xiàng)說明: -m表示運(yùn)行包里面的模塊,執(zhí)行這個(gè)命令的時(shí)候,需要進(jìn)入你自己指定靜態(tài)文件的目錄,然后通過瀏覽器就能訪問對(duì)應(yīng)的 html文件了,這樣一個(gè)靜態(tài)的web服務(wù)器就搭建好了。
訪問搭建的靜態(tài)Web服務(wù)器
通過瀏覽器訪問搭建的靜態(tài)Web服務(wù)器
查看瀏覽器和搭建的靜態(tài)Web服務(wù)器的通信過程
靜態(tài)Web服務(wù)器是為發(fā)出請(qǐng)求的瀏覽器提供靜態(tài)文檔的程序,
搭建Python自帶的Web服務(wù)器使用python3 –m http.server 端口號(hào) 這個(gè)命令即可,端口號(hào)不指定默認(rèn)是8000

靜態(tài)Web服務(wù)器-返回固定頁(yè)面數(shù)據(jù)

開發(fā)自己的靜態(tài)Web服務(wù)器
實(shí)現(xiàn)步驟:
編寫一個(gè)TCP服務(wù)端程序
獲取瀏覽器發(fā)送的http請(qǐng)求報(bào)文數(shù)據(jù)
讀取固定頁(yè)面數(shù)據(jù),把頁(yè)面數(shù)據(jù)組裝成HTTP響應(yīng)報(bào)文數(shù)據(jù)發(fā)送給瀏覽器。
HTTP響應(yīng)報(bào)文數(shù)據(jù)發(fā)送完成以后,關(guān)閉服務(wù)于客戶端的套接字。
靜態(tài)Web服務(wù)器-返回固定頁(yè)面數(shù)據(jù)的示例代碼

import socketif __name__ == '__main__':# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用, 程序退出端口立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 綁定端口號(hào)tcp_server_socket.bind(("", 9000))# 設(shè)置監(jiān)聽tcp_server_socket.listen(128)while True:# 等待接受客戶端的連接請(qǐng)求new_socket, ip_port = tcp_server_socket.accept()# 代碼執(zhí)行到此,說明連接建立成功recv_client_data = new_socket.recv(4096)# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_client_content = recv_client_data.decode("utf-8")print(recv_client_content)with open("static/index.html", "rb") as file:# 讀取文件數(shù)據(jù)file_data = file.read()# 響應(yīng)行response_line = "HTTP/1.1 200 OK\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)# 關(guān)閉服務(wù)與客戶端的套接字new_socket.close() 編寫一個(gè)TCP服務(wù)端程序tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 循環(huán)接受客戶端的連接請(qǐng)求 while True:conn_socket, ip_port = tcp_server_socket.accept() 獲取瀏覽器發(fā)送的http請(qǐng)求報(bào)文數(shù)據(jù)client_request_data = conn_socket.recv(4096) 讀取固定頁(yè)面數(shù)據(jù),把頁(yè)面數(shù)據(jù)組裝成HTTP響應(yīng)報(bào)文數(shù)據(jù)發(fā)送給瀏覽器。response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body conn_socket.send(response_data) HTTP響應(yīng)報(bào)文數(shù)據(jù)發(fā)送完成以后,關(guān)閉服務(wù)于客戶端的套接字。conn_socket.close()

靜態(tài)Web服務(wù)器-返回指定頁(yè)面數(shù)據(jù)

目前的Web服務(wù)器,不管用戶訪問什么頁(yè)面,返回的都是固定頁(yè)面的數(shù)據(jù),接下來需要根據(jù)用戶的請(qǐng)求返回指定頁(yè)面的數(shù)據(jù)
返回指定頁(yè)面數(shù)據(jù)的實(shí)現(xiàn)步驟:
獲取用戶請(qǐng)求資源的路徑
根據(jù)請(qǐng)求資源的路徑,讀取指定文件的數(shù)據(jù)
組裝指定文件數(shù)據(jù)的響應(yīng)報(bào)文,發(fā)送給瀏覽器
判斷請(qǐng)求的文件在服務(wù)端不存在,組裝404狀態(tài)的響應(yīng)報(bào)文,發(fā)送給瀏覽器
靜態(tài)Web服務(wù)器-返回指定頁(yè)面數(shù)據(jù)的示例代碼

import socketdef main():# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用, 程序退出端口立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 綁定端口號(hào)tcp_server_socket.bind(("", 9000))# 設(shè)置監(jiān)聽tcp_server_socket.listen(128)while True:# 等待接受客戶端的連接請(qǐng)求new_socket, ip_port = tcp_server_socket.accept()# 代碼執(zhí)行到此,說明連接建立成功recv_client_data = new_socket.recv(4096)if len(recv_client_data) == 0:print("關(guān)閉瀏覽器了")new_socket.close()return# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_client_content = recv_client_data.decode("utf-8")print(recv_client_content)# 根據(jù)指定字符串進(jìn)行分割, 最大分割次數(shù)指定2request_list = recv_client_content.split(" ", maxsplit=2)# 獲取請(qǐng)求資源路徑request_path = request_list[1]print(request_path)# 判斷請(qǐng)求的是否是根目錄,如果條件成立,指定首頁(yè)數(shù)據(jù)返回if request_path == "/":request_path = "/index.html"try:# 動(dòng)態(tài)打開指定文件with open("static" + request_path, "rb") as file:# 讀取文件數(shù)據(jù)file_data = file.read()except Exception as e:# 請(qǐng)求資源不存在,返回404數(shù)據(jù)# 響應(yīng)行response_line = "HTTP/1.1 404 Not Found\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"with open("static/error.html", "rb") as file:file_data = file.read()# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)else:# 響應(yīng)行response_line = "HTTP/1.1 200 OK\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)finally:# 關(guān)閉服務(wù)與客戶端的套接字new_socket.close()if __name__ == '__main__':main()

獲取用戶請(qǐng)求資源的路徑
request_list = client_request_conent.split(” ”, maxsplit=2)
request_path = request_list[1]
根據(jù)請(qǐng)求資源的路徑,讀取請(qǐng)求指定文件的數(shù)據(jù)
with open(“static” + request_path, “rb”) as file:
file_data = file.read()
組裝指定文件數(shù)據(jù)的響應(yīng)報(bào)文,發(fā)送給瀏覽器
response_data = (response_line + response_header + “\r\n”).encode(“utf-8”) + response_body
conn_socket.send(response_data)
判斷請(qǐng)求的文件在服務(wù)端不存在,組裝404狀態(tài)的響應(yīng)報(bào)文,發(fā)送給瀏覽器
try:
# 打開指定文件,代碼省略…
except Exception as e:
conn_socket.send(404響應(yīng)報(bào)文數(shù)據(jù))

靜態(tài)Web服務(wù)器-多任務(wù)版

靜態(tài)Web服務(wù)器的問題
目前的Web服務(wù)器,不能支持多用戶同時(shí)訪問,只能一個(gè)一個(gè)的處理客戶端的請(qǐng)求,那么如何開發(fā)多任務(wù)版的web服務(wù)器同時(shí)處理 多個(gè)客戶端的請(qǐng)求?
可以使用多線程,比進(jìn)程更加節(jié)省內(nèi)存資源。
多任務(wù)版web服務(wù)器程序的實(shí)現(xiàn)步驟:
當(dāng)客戶端和服務(wù)端建立連接成功,創(chuàng)建子線程,使用子線程專門處理客戶端的請(qǐng)求,防止主線程阻塞。
把創(chuàng)建的子線程設(shè)置成為守護(hù)主線程,防止主線程無法退出。
靜態(tài)Web服務(wù)器-多任務(wù)版的示例代碼

import socket import threading# 處理客戶端的請(qǐng)求 def handle_client_request(new_socket):# 代碼執(zhí)行到此,說明連接建立成功recv_client_data = new_socket.recv(4096)if len(recv_client_data) == 0:print("關(guān)閉瀏覽器了")new_socket.close()return# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_client_content = recv_client_data.decode("utf-8")print(recv_client_content)# 根據(jù)指定字符串進(jìn)行分割, 最大分割次數(shù)指定2request_list = recv_client_content.split(" ", maxsplit=2)# 獲取請(qǐng)求資源路徑request_path = request_list[1]print(request_path)# 判斷請(qǐng)求的是否是根目錄,如果條件成立,指定首頁(yè)數(shù)據(jù)返回if request_path == "/":request_path = "/index.html"try:# 動(dòng)態(tài)打開指定文件with open("static" + request_path, "rb") as file:# 讀取文件數(shù)據(jù)file_data = file.read()except Exception as e:# 請(qǐng)求資源不存在,返回404數(shù)據(jù)# 響應(yīng)行response_line = "HTTP/1.1 404 Not Found\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"with open("static/error.html", "rb") as file:file_data = file.read()# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)else:# 響應(yīng)行response_line = "HTTP/1.1 200 OK\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)finally:# 關(guān)閉服務(wù)與客戶端的套接字new_socket.close()# 程序入口函數(shù) def main():# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用, 程序退出端口立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 綁定端口號(hào)tcp_server_socket.bind(("", 9000))# 設(shè)置監(jiān)聽tcp_server_socket.listen(128)while True:# 等待接受客戶端的連接請(qǐng)求new_socket, ip_port = tcp_server_socket.accept()print(ip_port)# 當(dāng)客戶端和服務(wù)器建立連接程,創(chuàng)建子線程sub_thread = threading.Thread(target=handle_client_request, args=(new_socket,))# 設(shè)置守護(hù)主線程sub_thread.setDaemon(True)# 啟動(dòng)子線程執(zhí)行對(duì)應(yīng)的任務(wù)sub_thread.start()if __name__ == '__main__':main()

當(dāng)客戶端和服務(wù)端建立連接成功,創(chuàng)建子線程,使用子線程專門處理客戶端的請(qǐng)求,防止主線程阻塞。
while True:
conn_socket, ip_port = tcp_server_socket.accept()
# 開辟子線程并執(zhí)行對(duì)應(yīng)的任務(wù)
sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,))
把創(chuàng)建的子線程設(shè)置成為守護(hù)主線程,防止主線程無法退出。
開辟子線程并執(zhí)行對(duì)應(yīng)的任務(wù)
sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,))
sub_thread.setDaemon(True) # 設(shè)置守護(hù)主線程
sub_thread.start()

靜態(tài)Web服務(wù)器-面向?qū)ο箝_發(fā)

以面向?qū)ο蟮姆绞介_發(fā)靜態(tài)Web服務(wù)器
實(shí)現(xiàn)步驟:
把提供服務(wù)的Web服務(wù)器抽象成一個(gè)類(HTTPWebServer)
提供Web服務(wù)器的初始化方法,在初始化方法里面創(chuàng)建socket對(duì)象
提供一個(gè)開啟Web服務(wù)器的方法,讓W(xué)eb服務(wù)器處理客戶端請(qǐng)求操作。

靜態(tài)Web服務(wù)器-面向?qū)ο箝_發(fā)的示例代碼

import socket import threading# 定義web服務(wù)器類 class HttpWebServer(object):def __init__(self):# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用, 程序退出端口立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 綁定端口號(hào)tcp_server_socket.bind(("", 9000))# 設(shè)置監(jiān)聽tcp_server_socket.listen(128)# 保存創(chuàng)建成功的服務(wù)器套接字self.tcp_server_socket = tcp_server_socket# 處理客戶端的請(qǐng)求@staticmethoddef handle_client_request(new_socket):# 代碼執(zhí)行到此,說明連接建立成功recv_client_data = new_socket.recv(4096)if len(recv_client_data) == 0:print("關(guān)閉瀏覽器了")new_socket.close()return# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_client_content = recv_client_data.decode("utf-8")print(recv_client_content)# 根據(jù)指定字符串進(jìn)行分割, 最大分割次數(shù)指定2request_list = recv_client_content.split(" ", maxsplit=2)# 獲取請(qǐng)求資源路徑request_path = request_list[1]print(request_path)# 判斷請(qǐng)求的是否是根目錄,如果條件成立,指定首頁(yè)數(shù)據(jù)返回if request_path == "/":request_path = "/index.html"try:# 動(dòng)態(tài)打開指定文件with open("static" + request_path, "rb") as file:# 讀取文件數(shù)據(jù)file_data = file.read()except Exception as e:# 請(qǐng)求資源不存在,返回404數(shù)據(jù)# 響應(yīng)行response_line = "HTTP/1.1 404 Not Found\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"with open("static/error.html", "rb") as file:file_data = file.read()# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)else:# 響應(yīng)行response_line = "HTTP/1.1 200 OK\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)finally:# 關(guān)閉服務(wù)與客戶端的套接字new_socket.close()# 啟動(dòng)web服務(wù)器進(jìn)行工作def start(self):while True:# 等待接受客戶端的連接請(qǐng)求new_socket, ip_port = self.tcp_server_socket.accept()# 當(dāng)客戶端和服務(wù)器建立連接程,創(chuàng)建子線程sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))# 設(shè)置守護(hù)主線程sub_thread.setDaemon(True)# 啟動(dòng)子線程執(zhí)行對(duì)應(yīng)的任務(wù)sub_thread.start()# 程序入口函數(shù) def main():# 創(chuàng)建web服務(wù)器對(duì)象web_server = HttpWebServer()# 啟動(dòng)web服務(wù)器進(jìn)行工作web_server.start()if __name__ == '__main__':main()

把提供服務(wù)的Web服務(wù)器抽象成一個(gè)類(HTTPWebServer)
class HttpWebServer(object):
提供Web服務(wù)器的初始化方法,在初始化方法里面創(chuàng)建socket對(duì)象
def init(self):
#初始化服務(wù)端套接字,設(shè)置監(jiān)聽,代碼省略…
提供一個(gè)開啟Web服務(wù)器的方法,讓W(xué)eb服務(wù)器處理客戶端請(qǐng)求操作。
def start(self):
while True:
service_client_socket, ip_port = self.tcp_server_socket.accept()
# 連接建立成功,開辟子線程處理客戶端的請(qǐng)求
sub_thread = threading.Thread(target=self.handle_client_request, args=(service_client_socket,))
sub_thread.start()

靜態(tài)Web服務(wù)器-命令行啟動(dòng)動(dòng)態(tài)綁定端口號(hào)

開發(fā)命令行啟動(dòng)動(dòng)態(tài)綁定端口號(hào)的靜態(tài)web服務(wù)器
實(shí)現(xiàn)步驟:
獲取執(zhí)行python程序的終端命令行參數(shù)
判斷參數(shù)的類型,設(shè)置端口號(hào)必須是整型
給Web服務(wù)器類的初始化方法添加一個(gè)端口號(hào)參數(shù),用于綁定端口號(hào)
靜態(tài)Web服務(wù)器-命令行啟動(dòng)動(dòng)態(tài)綁定端口號(hào)的示例代碼

import socket import threading import sys# 定義web服務(wù)器類 class HttpWebServer(object):def __init__(self, port):# 創(chuàng)建tcp服務(wù)端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設(shè)置端口號(hào)復(fù)用, 程序退出端口立即釋放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 綁定端口號(hào)tcp_server_socket.bind(("", port))# 設(shè)置監(jiān)聽tcp_server_socket.listen(128)# 保存創(chuàng)建成功的服務(wù)器套接字self.tcp_server_socket = tcp_server_socket# 處理客戶端的請(qǐng)求@staticmethoddef handle_client_request(new_socket):# 代碼執(zhí)行到此,說明連接建立成功recv_client_data = new_socket.recv(4096)if len(recv_client_data) == 0:print("關(guān)閉瀏覽器了")new_socket.close()return# 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼recv_client_content = recv_client_data.decode("utf-8")print(recv_client_content)# 根據(jù)指定字符串進(jìn)行分割, 最大分割次數(shù)指定2request_list = recv_client_content.split(" ", maxsplit=2)# 獲取請(qǐng)求資源路徑request_path = request_list[1]print(request_path)# 判斷請(qǐng)求的是否是根目錄,如果條件成立,指定首頁(yè)數(shù)據(jù)返回if request_path == "/":request_path = "/index.html"try:# 動(dòng)態(tài)打開指定文件with open("static" + request_path, "rb") as file:# 讀取文件數(shù)據(jù)file_data = file.read()except Exception as e:# 請(qǐng)求資源不存在,返回404數(shù)據(jù)# 響應(yīng)行response_line = "HTTP/1.1 404 Not Found\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"with open("static/error.html", "rb") as file:file_data = file.read()# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)else:# 響應(yīng)行response_line = "HTTP/1.1 200 OK\r\n"# 響應(yīng)頭response_header = "Server: PWS1.0\r\n"# 響應(yīng)體response_body = file_data# 拼接響應(yīng)報(bào)文response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body# 發(fā)送數(shù)據(jù)new_socket.send(response_data)finally:# 關(guān)閉服務(wù)與客戶端的套接字new_socket.close()# 啟動(dòng)web服務(wù)器進(jìn)行工作def start(self):while True:# 等待接受客戶端的連接請(qǐng)求new_socket, ip_port = self.tcp_server_socket.accept()# 當(dāng)客戶端和服務(wù)器建立連接程,創(chuàng)建子線程sub_thread = threading.Thread(target=self.handle_client_request, args=(new_socket,))# 設(shè)置守護(hù)主線程sub_thread.setDaemon(True)# 啟動(dòng)子線程執(zhí)行對(duì)應(yīng)的任務(wù)sub_thread.start()# 程序入口函數(shù) def main():print(sys.argv)# 判斷命令行參數(shù)是否等于2,if len(sys.argv) != 2:print("執(zhí)行命令如下: python3 xxx.py 8000")return# 判斷字符串是否都是數(shù)字組成if not sys.argv[1].isdigit():print("執(zhí)行命令如下: python3 xxx.py 8000")return# 獲取終端命令行參數(shù)port = int(sys.argv[1])# 創(chuàng)建web服務(wù)器對(duì)象web_server = HttpWebServer(port)# 啟動(dòng)web服務(wù)器進(jìn)行工作web_server.start()if __name__ == '__main__':main()

獲取執(zhí)行python程序的終端命令行參數(shù)
sys.argv
判斷參數(shù)的類型,設(shè)置端口號(hào)必須是整型
if not sys.argv[1].isdigit():
print(“啟動(dòng)命令如下: python3 xxx.py 9090”)
return
port = int(sys.argv[1])
給Web服務(wù)器類的初始化方法添加一個(gè)端口號(hào)參數(shù),用于綁定端口號(hào)
def init(self, port):
self.tcp_server_socket.bind((“”, port))

總結(jié)

以上是生活随笔為你收集整理的网络编程学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。