天天看點

實作通過公網遠端通路運作在伺服器上的Python程式

前言

前段時間學習了HTTP的原理,并用Python語言實作了一個簡單的HTTP伺服器(帶有多線程功能的哦);後面突發一想,我能把挂在本地伺服器上,每次運作都需要打開虛拟機并運作程式(這樣真的很麻煩)。我想起之前阿裡雲伺服器打折的時候,也跟随着小夥伴一起入手了一個最低配的,之前這個伺服器隻是用來刷票的,現在終于能發揮他的作用了。

準備

1、程式

簡單描述:我這個程式是能通過浏覽器,通路程式并通過伺服器上的資源路徑把資源傳回給浏覽器并呈現出來,下面是這個程式的源碼:

# 實作步驟:
#
# 編寫一個TCP服務端程式
# 擷取浏覽器發送的http請求封包資料
# 讀取固定頁面資料,把頁面資料組裝成HTTP響應封包資料發送給浏覽器。
# HTTP響應封包資料發送完成以後,關閉服務于用戶端的套接字。


#1.導入子產品
import socket
import threading
from urllib import request
import sys

# 注意,這段代碼必須在指令行中運作。

# 實作步驟:
#
# 把提供服務的Web伺服器抽象成一個類(HTTPWebServer)
# 提供Web伺服器的初始化方法,在初始化方法裡面建立socket對象
# 提供一個開啟Web伺服器的方法,讓Web伺服器處理用戶端請求操作。
class WebServer(object):
    def __init__(self):
        # 2.建立socket對象
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 設定位址複用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 3.綁定端口号
        tcp_server_socket.bind(("", 3389))
        # 4.設定監聽模式
        tcp_server_socket.listen(100)
        # 設定一個執行個體屬性
        self.tcp_server_socket = tcp_server_socket


    def start(self):
        while True:
            # 5.等待用戶端的連結(傳回新的socket)
            new_service_client, client_address_info = self.tcp_server_socket.accept()
            print("用戶端連結: ", client_address_info)

            # handler_client(new_service_client)
            # 一旦有用戶端連結,我們就建立一個新的子線程服務用戶端
            sub_thread = threading.Thread(target=self.handler_client, args=(new_service_client,))
            # 設定子線程為守護線程,主線程結束時,所有守護線程也結束
            sub_thread.setDaemon(True)
            # 啟動子線程
            sub_thread.start()

    # 執行個體方法:對象方法 (self)
    # def handler_client(self, new_service_client):

    # 類方法: (cls)

    # 靜态方法
    @staticmethod
    def handler_client(new_service_client):

        # 6.接收浏覽器發送的資料(請求封包)
        recv_data = new_service_client.recv(4096)
        if len(recv_data) == 0:
            print("浏覽器關閉(用戶端下線)")
            new_service_client.close()
            return
        print(recv_data)
        recv_content = recv_data.decode("utf-8")
        print("請求封包: ", recv_content)
        #   6.1 解析請求封包擷取資源路徑
        #       GET /index.html HTTP/1.1
        #       按照空格分割,最多分割兩次
        recv_list = recv_content.split(" ", maxsplit=2)
        #   6.2 擷取資源路徑
        #       file_path = xxx[1]
        file_path = recv_list[1]
        print(file_path)

        # 判斷file_path是否是/, 指向首頁index.html
        if file_path == "/":
            file_path = "/index.html"
		# 因為資源路徑包含中文,浏覽器發送請求時會用utf-8的方式對包含中文的資源路徑進行編碼,是以若包含中文需要先解碼
        file_path = request.unquote(file_path)
        print(file_path)
        try:
            # 7.放送資料給浏覽器
            #   7.1 打開指定頁面檔案(static + file_path)
            # 打開的檔案找不到,會抛出異常
            with open("notes" + file_path, "rb") as file:
                file_data = file.read()

        except Exception as e:
            # 資源路徑找不到

            #   7.1 打開指定頁面檔案(static + file_path)
            with open("notes/error.html", "rb") as file:
                file_data = file.read()

            #   7.2 拼接成響應封包資料
            #       響應行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            #       響應頭
            response_head = "Server: NBW/1.0\r\n"
        else:
            # 找到資源路徑
            #   7.2 拼接成響應封包資料
            #       響應行
            response_line = "HTTP/1.1 200 OK\r\n"
            #       響應頭
            response_head = "Server: NBW/1.0\r\n"
            #       空行
            #       \r\n

        #       響應體
        response_body = file_data

        response_data = (response_line + response_head + "\r\n").encode("utf-8") + response_body
        #   7.3 發送資料給浏覽器
        new_service_client.send(response_data)
        # 8.關閉連結
        new_service_client.close()

def main():
    w1 = WebServer()
    # 啟動w1
    w1.start()

if __name__ == '__main__':
    main()

           

2、伺服器

我這裡準備的是阿裡的伺服器,

Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-142-generic x86_64)

實作通過公網遠端通路運作在伺服器上的Python程式

過程

1、通過ssh服務把python檔案和資源檔案上傳到伺服器的指定目錄中(自己得記住),我這裡是放在Desktop上的。

實作通過公網遠端通路運作在伺服器上的Python程式

2、通過

python3 07-web靜态伺服器-傳回指定頁面-多任務版本-面向對象程式設計......py

把這個程式運作起來,在本地的浏覽器通過公網ip+端口發現無法通路。

注:確定程式調用的端口已經對外公開了,我這裡設定的端口是:3389

實作通過公網遠端通路運作在伺服器上的Python程式

3、把端口号設定好後,再啟動程式,再通過本地浏覽器通路(我的ip+port:http://47.107.138.151:3389),發現資源可以通路已經配置好的資源了。

實作通過公網遠端通路運作在伺服器上的Python程式

4、把cmd視窗關閉之後,會發現剛剛運作的程式停了,剛剛的資源又無法通路了;下面介紹一種

# *.py是你的py檔案名
nohup python *.py &
           

這裡有更詳細的介紹在伺服器端,如何一直運作你的python代碼

繼續閱讀