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

通过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 访问结果

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

轻松玩转Python正则表达式

引言 正则表达式是一种强大的文本匹配和处理工具,广泛应用于各种编程语言中。在Python中,我们可以使用内置的re模块来处理正则表达式。本文将带您从入门到精通,逐步介绍Python中的正则表达式用法,并提供实例演示。 1. 正则表达式…

JVM理论(二)类加载子系统

类加载流程 类加载流程 类加载器子系统负责从文件系统或者网络中加载class文件,class文件的文件头有特定的文件标识(CAFEBABE是JVM识别class文件是否合法的依据)classLoader只负责文件的加载,而执行引擎决定它是否被执行加载类的信息存放在运行时数据区的方法区中,方法区还包括…

VBA代码如何切换word和excel(3)

【分享成果,随喜正能量】人不能因为一件好事,高兴一整年,却能因为一个创伤,郁郁终生。痛苦给人的刺激,总是远远大于快乐。成年人的烦恼,和谁说都不合适,悲喜自渡,他人难悟。人最强大…

4-软件错误(BUG)

目录 1.什么是bug? 2.如何描述一个bug? ①发现问题的版本 ②问题出现的环境 ③错误重现的步骤 ④预期行为的描述 ⑤错误行为的描述 ⑥其他 ⑦不要把多个bug放到一起 PS:案例1 PS:案例2 3.如何定义bug的级别? ①Blocker&#x…

springboot+mysql财务管理系统

财务管理系统的开发运用java技术、springboot框架,MIS的总体思想,以及Mysql等技术的支持下共同完成了该系统的开发,实现了财务管理的信息化,使员工体验到更优秀的财务管理,管理员管理操作将更加方便,实现目…

10.3.2 【Linux】历史命令:history

[dmtsaistudy ~]$ alias hhistory 在正常的情况下,历史命令的读取与记录是这样的: 当我们以 bash 登陆 Linux 主机之后,系统会主动的由主文件夹的 ~/.bash_history 读取以前曾经下过的指令,那么 ~/.bash_history 会记录几笔数据呢…

网络编程7——IP协议(子网掩码,NAT机制,IPv6协议) + 以太网

文章目录 前言一、IP协议协议头格式认识IP地址格式组成子网掩码 地址管理1.动态分配2.NAT机制3.IPv6协议 路由选择 二、以太网以太网帧格式认识MTU 总结 前言 本人是一个普通程序猿!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果你也对编程感兴趣的话&#x…

MongoDB【MongoDB索引Index (索引概述、索引类型、复合索引、)】(三)-全面详解(学习总结---从入门到深化)

目录 MongoDB索引Index 聚合操作 通过聚合操作可以处理多个文档,并返回计算后的结果。 对多个文档进行分组对分组的文档执行操作并返回单个结果分析数据变化 聚合管道 分别由多个阶段来处理文档,每个阶段的输出是下个阶段的输入, 返回的是…

GitLab名词介绍

GitLab名词介绍 分支:active、stale、default、protected IDEA中git面板:本地、远程、HEAD 合并时的选项:Delete、squash 查看Git常用操作 分支:active、stale、default、protected 在分支页面下,有active、stale…

Acwing 849. Dijkstra求最短路 I

Acwing 849. Dijkstra求最短路 I 链接:849. Dijkstra求最短路 I - AcWing题库 /*题解:dijkstra算法模板对于单源最短路径dijkstra1.每次找到当前距离源最近的节点 作为确定距离的点2.通过这个点看能否让其他的节点来松弛其他点到源的距离重复12操作*/ #include<algorithm&g…

端口映射的作用?如何在路由器上做端口映射

一、端口映射作用 路由器中设置端口映射的主要作用&#xff0c;就是让Internet上的其他用户&#xff0c;可以访问你路由器下面电脑中的数据(软件、文件)。 当家里的电脑使用路由器上网后&#xff0c;在Internet下的其它电脑、手机等网络设备&#xff0c;将无法自接访问你电脑…

linux常用的命令

一.操作目录命令 1.1 ls 命令 语法&#xff1a; ls [选项] [目录或文件] 功能: 对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含…

仙境传说RO:添加自定义道具

仙境传说RO&#xff1a;添加自定义道具 大家好&#xff0c;我是艾西今天和大家聊一下仙境传说RO怎么添加自定义道具。在我们开服时加入一些道具模组等往往会让我们的服务器更有特色以及消费点&#xff0c;那么让我们直接进入正题开始操作&#xff1a;&#xff08;此处我们讲的…

【C#】Kestrel和IIS服务器下的同步与异步配置

最近在回看自己写的代码时&#xff0c;发现服务配置里最开头写了两段代码&#xff0c;第一感觉&#xff0c;这是啥功能&#xff0c;太久有点生疏了&#xff0c;经过一顿搜索和回顾&#xff0c;简单整理如下 目录 1、Kestrel服务器1.1、跨平台1.2、高性能1.3、可扩展性1.4、安全…

零矩阵

暴力解法&#xff1a;先全部检索&#xff0c;定位0所在的位置&#xff0c; 记录到新的数组 数组的行列分别进行去重 数组中记录的行列赋值为零 如果直接修改&#xff0c;在行被修改之后&#xff0c;修改列时会因为行已经被修改产生影响 import org.junit.Test;import java.uti…

二十三种设计模式第十四篇--策略模式

策略模式&#xff1a;主要围绕一个类的行为或者其算法在运行时更改&#xff0c;也是一种行为型模式。 在软件开发中&#xff0c;我们经常遇到需要根据不同的情况选择不同算法或行为的情况。传统的做法是使用大量的条件语句来实现这种逻辑&#xff0c;但这样的实现方式往往难以…

Python模拟MQTT v3.1.1服务器

示例代码 import logging import asyncio from hbmqtt.broker import Broker# 设置日志级别为DEBUG logging.basicConfig(levellogging.DEBUG)# 创建MQTT服务器 broker Broker()# 启动MQTT服务器 async def start_broker():await broker.start()# 停止MQTT服务器 async def s…

python离线安装ibm_db

下载离线包ibm_db以及clidriver 下载imb_db 在pypi官方网站https://pypi.org/project/ibm-db/#files下载离线安装包ibm_db-3.0.2.tar.gz。下载clidriver 下载地址&#xff1a;https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/nt32_odbc_cli.…

C语言学生信息管理系统

C语言版学生信息管理系统 一&#xff0c;开发环境 操作系统&#xff1a;windows10, windows11, linux, mac等。开发工具&#xff1a;Qt, vscode, visual studio等开发语言&#xff1a;c语言 二&#xff0c;功能需求 1. 用户界面: 提供一个简洁的文本界面&#xff0c;用户可…

AI 对抗超级细菌:麦克马斯特大学利用深度学习发现新型抗生素 abaucin

内容一览&#xff1a;鲍曼不动杆菌是一种常见的医院获得性革兰氏阴性病原体&#xff0c;通常表现出多重耐药性。利用传统方法&#xff0c;发现抑制此菌的新型抗生素很困难。但利用机器学习可以快速探索化学空间&#xff0c;从而增加发现新型抗菌分子的可能性。近期&#xff0c;…