首页技术文章正文

实现通过公网远程访问运行在服务器上的Python程序【黑马python培训】

更新时间:2022年11月16日 15时43分07秒 来源:黑马程序员论坛

黑马中级程序员课程

前言
前段时间学习了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)



过程

1、通过ssh服务把python文件和资源文件上传到服务器的指定目录中(自己得记住),我这里是放在Desktop上的。



2、通过 `python3 07-web静态服务器-返回指定页面-多任务版本-面向对象编程......py` 把这个程序运行起来,在本地的浏览器通过公网ip+端口发现无法访问。
注:确保程序调用的端口已经对外公开了,我这里设置的端口是:3389


3、把端口号设置好后,再启动程序,再通过本地浏览器访问(我的ip+port:http://47.107.138.151:3389),发现资源可以访问已经配置好的资源了。



4、把cmd窗口关闭之后,会发现刚刚运行的程序停了,刚刚的资源又无法访问了;下面介绍一种

# *.py是你的py文件名
nohup python *.py &

这里有更详细的介绍[在服务器端,如何一直运行你的python代码](https://blog.csdn.net/u013421629/article/details/79174313/)


推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程【点击播放】

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


分享到:
在线咨询 我要报名
和我们在线交谈!