Python学习笔记-基于socket基础的http服务端程序

news2024/9/22 5:30:12

通过HTTP协议可以进行通信可以规范化的进行网络间通信。下面技术第一个http服务器小程序。简单的记录第一个试手程序。

1.http通信的基本流程

整个流程对应四层网络架构:应用层、传输层、网络层、链路层。有的部分已经封装,不需要我们再行处理。

2.服务器程序设置

2.1 创建一个socket对象

self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

第一个参数是指定IP协议,第二个参数用于指定通信方式。

官方构造函数解释如下:

    def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
        # For user code address family and type values are IntEnum members, but
        # for the underlying _socket.socket they're just integers. The
        # constructor of _socket.socket converts the given argument to an
        # integer automatically.
        if fileno is None:
            if family == -1:
                family = AF_INET
            if type == -1:
                type = SOCK_STREAM
            if proto == -1:
                proto = 0
        _socket.socket.__init__(self, family, type, proto, fileno)
        self._io_refs = 0
        self._closed = False

基本参数信息如下:

AF_INET = AddressFamily.AF_INET

IPv4地址

AF_INET6 = AddressFamily.AF_INET6

IPv6地址

SOCK_STREAM = SocketKind.SOCK_STREAM

基于TCP传输

SOCK_DGRAM = SocketKind.SOCK_DGRAM

基于UDP传输

2.2 绑定IP和端口

def bind(self, __address: _Address) -> None: ...

_Address: TypeAlias = tuple[Any, ...] | str | ReadableBuffer

指定一个地址进行绑定。

通过元组的形式指定IP地址和端口号:

self.server_socket.bind(("", port))

注意,需要使用元组型号的数据,第一个参数是IP地址,第二个参数是端口号,使用空字符串”“默认为本地IP地址:127.0.0.1。

2.3 启动监听

def listen(self, __backlog: int = ...) -> None: ...

设置监听数量,即允许同时连接的最大客户端数量。

2.4 接收请求

    def accept(self):
        """accept() -> (socket object, address info)

        Wait for an incoming connection.  Return a new socket
        representing the connection, and the address of the client.
        For IP sockets, the address info is a pair (hostaddr, port).
        """
        fd, addr = self._accept()
        sock = socket(self.family, self.type, self.proto, fileno=fd)
        # Issue #7995: if no default timeout is set and the listening
        # socket had a (non-zero) timeout, force the new socket in blocking
        # mode to override platform-specific socket flags inheritance.
        if getdefaulttimeout() is None and self.gettimeout():
            sock.setblocking(True)
        return sock, addr

通过accept函数返回请求对象,返回两个参数,一个是请求的socket,一个是请求的地址信息。

client_socket, client_address = self.server_socket.accept()

2.5 处理请求

处理请求就相当于字符串处理,解析报文,进行对应处理。

2.6 应答

def send(self, __data: ReadableBuffer, __flags: int = ...) -> int: ...

通过send函数将bytes数据返回给客户端。

client_socket.send(bytes(response, "utf-8"))

2.7 关闭socket

client_socket.close()

关闭客户端的socket。

注意:此处关闭的是获取到的客户端socket,不是服务器的socket。

3. 示例代码

3.1 服务端代码

# _*_ coding:utf-8 _*_

import socket
import re
import os
from multiprocessing import Process

HTML_ROOT_DIR = "./zero.staticserver/views"


class HTTPServer(object):
    """HTTP server"""

    def __init__(self) -> None:
        """init"""

        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        """初始化socket,IPV4,TCP协议"""

    def bind(self, port):
        """Binding port"""

        self.server_socket.bind(("", port))

    def start(self):
        """Start server"""

        self.server_socket.listen(20)   # 设置最大连接数20
        print("Server started.Waitting to connect...")

        while True:

            # 接收的客户端连接信息
            client_socket, client_address = self.server_socket.accept()
            print("Client Connected. IP:{0},Port:{1}",
                  client_address[0], client_address[1])
            process_client = Process(
                target=self.handle_client, args=(client_socket,))
            process_client.start()
            client_socket.close()

    def handle_client(self, client_socket: socket.socket):
        """handle of client"""

        request_data = client_socket.recv(1024)
        print("Request Data:", request_data)
        print("********逐行输出请求数据*********")

        request_lines = request_data.splitlines()
        for line in request_lines:
            print(line)

        print("********解析报文*********")
        request_start_line = request_lines[0]
        str_request_start_line = request_start_line.decode("utf-8")
        print(str_request_start_line)
        filename = re.match(r"\w+ +(/[^ ]*) ", str_request_start_line).group(1)
        print("File Name : {0}".format(filename))

        if filename == "/":
            filename = "index.html"

        print("root path : {0}".format(os.getcwd()))
        try:
            filepath = f"{HTML_ROOT_DIR}/{filename}"
            file = open(filepath, "rb")
        except IOError:
            # 返回异常
            response_start_line = "HTTP/1.1 404 Not Found"
            response_headers = "Server:First server"
            response_body = "The file is not found."
        else:
            # Read file data.
            filedata = file.read()
            file.close()

            response_start_line = "HTTP/1.1 200 OK"
            response_headers = "Server:First server"
            response_body = filedata.decode("utf-8")

        print("\r\n")
        response = f"{response_start_line}\r\n{response_headers}\r\n\r\n{response_body}"
        print("Response:\r\n{0}".format(response))
        client_socket.send(bytes(response, "utf-8"))
        # Close socket.
        client_socket.close()

3.2 访问结果

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/736045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哈夫曼树-算法

一、霍夫曼树基本概念: 路径:从树的一个结点到另外一个结点的分支构成这两个结点的路径 结点的长度:两节点之间路径的分支数 树的路径长度:从树根到每一个结点的长度之和,记做TL: 结点数目相同的二叉树中&#xff0…

LwIP系列(5):TCP 3次握手+4次挥手+状态机转换

前言 TCP的3次握手、4次挥手以及TCP状态机,是TCP的核心概念,我们在分析LwIp中TCP相关代码流程,也需要熟悉这些流程,本文就详细介绍这些概念。 TCP 3次握手、应用数据交互、4次挥手完整流程 TCP 为什么是3次握手,而不…

51单片机--动态数码管显示

文章目录 LED数码管一位晶体管多位一体数码管单片机上的数码管原理 静态数码管显示动态数码管显示 LED数码管 简介:LED数码管是一种常用的数字显示设备。它由多个发光二极(LED)封装在一起,形成“8”字型的器件。数码管通常由7段LE…

【从0开始离线数仓项目】——新能源汽车数仓项目介绍

目录 1、数据仓库概念 2、项目需求及架构设计 3、集群资源规划设计 4、车辆日志字段说明 1、数据仓库概念 数据仓库(Data Warehouse)是为企业提供数据支持,用以协助企业制定决策、改进业务流程和提高产品质量等方面的工具。它可以接收多种…

时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测,单列数据输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %% 清空环境变量 warnin…

Dart - dill文件序列化为可读文本(续)

文章目录 前言开发环境app.dill文件DEPS文件最后 前言 对前文Dart - dill文件序列化为可读文本做一些补充。 开发环境 macOS: 13.4Dart: 3.0.5Flutter: 3.10.5 app.dill文件 因为Flutter项目编译后会自动生成app.dill文件(位于项目根目录下的.dart_tool/flutte…

基于PyQt5的桌面图像调试仿真平台开发(9)去噪

系列文章目录 基于PyQt5的桌面图像调试仿真平台开发(1)环境搭建 基于PyQt5的桌面图像调试仿真平台开发(2)UI设计和控件绑定 基于PyQt5的桌面图像调试仿真平台开发(3)黑电平处理 基于PyQt5的桌面图像调试仿真平台开发(4)白平衡处理 基于PyQt5的桌面图像调试仿真平台开发(5)…

Detect-SLAM论文翻译

Detect-SLAM:实现目标检测与SLAM的互利共赢 摘要 - 尽管近年来在SLAM和目标检测方面取得了重大进展,但这两项任务仍然存在一系列挑战,例如动态环境中的SLAM和复杂环境中的目标检测。为了解决这些挑战,我们提出了一种新的机器人视觉系统&…

UE使用UnLua(一)

一、概述 Unlua是个功能丰富的插件,可以在UE中进行蓝图绑定,在Lua中进行逻辑开发,使用Lua热更新的特性,可以快速开发迭代表层逻辑 二、UnLua环境 首先下载UnLua的插件包,点击下载,不会吧不会吧还有人打不…

基于simulink使用前景检测跟踪汽车(附源码)

一、前言 此示例基于simulink演示如何使用高斯混合模型 (GMM) 检测和计数视频序列中的汽车。 二、模型 下图显示了使用前景检测跟踪汽车模型: 三、检测和跟踪结果 检测和计数汽车可用于分析交通模式。检测也是执行更复杂的任务&#xff0…

【Linux】C++项目实战-实际应用

目录 典型IO的两个阶段(网络IO)Linux上的五种IO模型1.阻塞 blocking2、非阻塞3、IO复用4、信号驱动5、异步 Web ServerHTTP协议(应用层的协议)简介概述工作原理HTTP请求格式HTTP响应报文格式HTTP请求方法(仅作了解)HTTP状态码 服务…

【Java|多线程与高并发】死锁以及哲学家吃饭问题

文章目录 1. 什么是死锁2. 哲学家吃饭问题3.如何解决死锁 1. 什么是死锁 死锁(Deadlock)是多线程编程中的一个常见问题,指的是两个或多个线程相互等待对方释放资源,导致程序无法继续执行的状态。 在一种典型的死锁情况中&#x…

建立点到多点的IPSec隧道(IKE安全策略方式)

目录 1. 组网需求1.1 网络拓扑1.2 配置思路1.3 版本 2. 配置USG5500 A2.1 基本配置2.2 配置域间包过滤规则2.3 配置到达分支的静态路由2.4 定义被保护的数据流2.5 配置名称为tran1的IPSec安全提议2.6 配置序号为10的IKE安全提议2.7 配置IKE Peer2.8 配置IPSec安全策略组map12.9…

哈工大计算机网络课程数据链路层协议详解之:多路访问控制(MAC)协议

哈工大计算机网络课程数据链路层协议详解之:多路访问控制(MAC)协议 在上一小节介绍完数据链路层功能和所提供的服务后,接下来我们介绍一个在数据链路层非常重要的一个协议:多路访问控制MAC协议。 多路访问控制主要是…

简易登录页面实现

导言 本文将介绍一个简单的登录页面的实现&#xff0c;使用HTML、CSS和JavaScript完成。该登录页面具有选项卡切换和表单提交功能。 HTML基础知识 首先&#xff0c;我们来了解一下HTML文档的基本结构&#xff1a; <!DOCTYPE html> <html> <head><titl…

python创建多个logging日志文件

为每一个计算过程创建一个单独的日志文件&#xff0c;并写入对应的结果&#xff0c;同时保留控制台输出的功能&#xff0c;控制台输出与日志文件记录可以分开单独控制。 import os import loggingdef creat_logger(log_path,logging_name,suf_name):if not os.path.exists(log…

NC65 输出打印模板设置流程

NC65 输出打印模板设置流程 一、添加打印模板 1、可以在单据模板初始化设置中生成打印模板&#xff08;这里以结算单为例&#xff09; 输入模板编码和名称&#xff0c;然后按确定即可。 此时&#xff0c;去输出模板初始化节点查看&#xff0c;就可以查看到刚才生成的打印模…

第五章 中央处理器 第六节指令流水线

5.6.1 指令流水线的概念 5.6.2 指令流水线的影响因素和分类

MySQL基础(五)视图、存储过程和存储函数、变量

目录 常见的数据库对象 ​编辑 视图 创建视图 改变视图 优缺点 存储过程与存储函数 创建存储过程 创建存储函数 存储过程和存储函数的区别 存储过程和函数的查看、修改、删除 查看 修改 删除 存储过程的优缺点 优点 缺点 变量 系统变量 查看系统变量 修改…

h5页面如何与原生交互

本文讲述h5页面跟原生通信&#xff0c;比如在app内&#xff0c;调用相机&#xff0c;获取相册内的图片&#xff0c;在app内拉起微信小程序等等&#xff0c;h5页面没有这么多权限能够直接调用移动端的原生能力&#xff0c;这个时候就需要与原生进行通讯&#xff0c;传递一个信号…