day30 UDP协议

本周安排

周二 socket编程
周三 粘包处理
周四 选课系统
    并发编程
周五多道技术 多进程
周六 IPC 互斥锁

常用模块 os* 操作系统 多数是文件操作 os.path 处理文件路径 shutil 高级文件处理模块 用起来更方便 sys 解释器相关 json* 一种序列化方式 json可以支持跨平台 pickle 一种序列化方式 仅在python可用 re* 正则表达式 用于处理字符串 主要是查找 匹配 验证 爬虫中 验证用户输入是否合法 hashlib* hash一种算法 输入一段任意长度的数据 输出一段固定长度的字符 也称之为特征码 用于加密 和 数据校验

logging* 输出日志(程序运行的日记 是为了 日后出现问题 有迹可循)  用字典来配置  需包含 handler formater filter logger

configparser   解析配置文件的模块   配置文件中只能有分区个选项

xml  可扩展标记语言  其优势在于 可以自定义文档的结构 如HTML中有头有尾
学习的重点是如何读取xml文档 并找到需要的标签

time*  时间相关的 time.time() 获取时间戳    time.sleep() 让程序休眠指定时间

subproces  子进程   由一个正在运行的程序开启的另一个程序 称之为子进程  当当前程序 无法处理用户请求 但是另一个程序可以处理时
qq 中点击网页链接  会打开浏览器

random* 随机数相关    抽奖   验证码  随机点名

shelve  序列化方式  只有一个open函数
其使用方式与字典一致   相当于一个自带序列化的字典

面向对象 一种编程思想 核心概念 类与对象 对象是什么? 具备某些特征和技能的结合体 是实际存在的 类是 一系列具备相同特征和技能的集合体 是一种抽象概念

三大特性
    封装
       隐藏内部实现细节 多外提供使用接口
       提高安全性 隔离复杂度  明确区分内外
       被封装的函数和属性 只能在当前类中使用
    继承
        是一种类与类之间的关系
        有了继承关系后 子类可以使用父类中已经存在的属性和方法
        其目的是减少代码冗余
        python 可以多继承
        属性查找顺序按照mro列表的顺序
            c3算法  如果存在菱形继承  先深度 (遇见了公共父类)在广度
                       不存在菱形 则 深度优先
    多态
        一个事物具备多种形态
        例如一个动物 有多种形态  如 猪狗牛羊
        不同的对象具备相同的方法  会产生不同结果
    
        要实现多态性 需要 先抽象得到到公共父类   然后子类去继承父类 并且覆盖父类中声明的方法
        abc模块可以强制子类必须实现父类的方法

        python中推荐鸭子类型   只要具备相同的方法就可以看做同一个类

     绑定方法
        对象绑定方法
        类绑定方法
        绑定给谁 就由谁来调用 并且在调用时 自动传入 对象或者类

     非绑定方法
        就是一个普通的函数

     面向对象的精髓 就是 把数据和处理数据的方法进行绑定

异常 什么是异常 程序运行的时候出现了错误 程序会立即停止执行 为什么要学习异常 是为了保证程序可以正常执行结束 为了提高程序的健壮性 如何处理异常 try 可能出现异常的代码 except 异常的类型 打印异常信息 尝试处理异常

else
    没有出现异常时执行
finally
    无论是否出现异常 最后都会执行
    可以做清理操作

自定义异常类型
    继承Exception
主动抛出异常
    raise 任何Exception的子类 或者 其对象

万能异常
    Exception 一定要打印异常信息

异常组成
    异常的类型
    异常的值
    追踪信息

    找最后一行 把它翻译一下
    如果最后一行不是你写的而是模块内部的 那就找你写最后一行

网络编程

编写基于网络通讯的应用程序 1.七层模型 应用层

传输层
        TCP/UDP工作在传输层
        要求 要联网的应用程序必具备端口号
        用于定位某台计算机上的某个应用程序
        TCP
        三次握手  建立连接
        四次挥手  断开连接
        为了保证数据的完整性

    网络层
        ip协议
        ip地址 四个十进制数 前三个是网络号 后一位是主机号  主机号为1是网关
        网关之间通过路由协议来找到对方

        有了ip之后 可以在全世界范围内定为到一台计算机

    链路层
        解析二进制的数据
        以太网协议工作在该层
        规定了二进制数据的分组方式
        一段二进制数据称之为数据帧  1518
        包含 head和data

        还规定了一个计算机必须有MAC地址  通过MAC就能定位局域网内的一台计算机

    物理层: 物理传输介质
        网线 光纤  无线网络
        能传输二进制数据

recv(1024)阻塞:直到操作系统缓冲区有数据为止

基础班

服务器端

import socket

# 买手机 默认得到是一个TCP的socket
server = socket.socket()

# 两行代码的效果是一样的
# socket的家族   AF_INET
# socket的类型
# SOCK_STREAM 对应的是TCP     SOCK_DGRAM 对应的是UDP

# server = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
# 创建基于UDP的socket
# server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)


server.bind(("127.0.0.1",16888))  # 绑定手机卡

server.listen() # 开始待机

# 得到对方的socket对象与地址
client,addr = server.accept() # 接收通话请求 # 该函数会阻塞 直到有连接请求过来


print("==========")
# buffersize 表示应用程序的缓冲区大小     recv其实是 从系统缓冲区读取数据到应用程序
data = client.recv(1024)   # 该函数会阻塞 直到操作缓冲区有数据位置
print("==========")

print("收到客户端发来的数据:%s" % data.decode("utf-8"))

# 发生的数据必须为bytes类型
client.send(data)


client.close() #挂断电话

server.close() # 关机

普通版 客户端

import socket

client = socket.socket()

client.connect(("127.0.0.1",16888))

client.send("hello 服务器".encode("utf-8"))


print("===================")
data = client.recv(1024)   # 该函数会阻塞 直到操作缓冲区有数据位置
print("===================")

print("收到服务器:%s" % data.decode("utf-8"))


client.close()

服务器 循环版

import socket

# 买手机 默认得到是一个TCP的socket
server = socket.socket()

# 两行代码的效果是一样的
# socket的家族   AF_INET
# socket的类型
# SOCK_STREAM 对应的是TCP     SOCK_DGRAM 对应的是UDP

# server = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
# 创建基于UDP的socket
# server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)


server.bind(("127.0.0.1",16888))  # 绑定手机卡

server.listen() # 开始待机

# 连接循环 可以不断接受新连接
while True:
    client, addr = server.accept()

    # 通讯循环 可以不断的收发数据
    while True:
        try:
            # 如果是windows 对方强行关闭连接 会抛出异常
            # 如果是linux 不会抛出异常 会死循环收到空的数据包
            data = client.recv(1024)
            if not data:
                client.close()
                break

            print("收到客户端发来的数据:%s" % data.decode("utf-8"))
            client.send(data)
        except ConnectionResetError:
            print("客户端强行关闭了连接")
            client.close()
            break
client.close() #挂断电话
server.close() # 关机

客户端 循环版

import socket

client = socket.socket()

client.connect(("127.0.0.1",16888))

while True:
    msg = input(">:")
    client.send(msg.encode("utf-8"))
    data = client.recv(1024)
    print("收到服务器:%s" % data.decode("utf-8"))

client.close()

UDP 服务端

import socket

# UDP协议 在创建socket是 只有一个类型不同
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,proto=0)

server.bind(("127.0.0.1",8888))


while True:
    data,addr = server.recvfrom(1024) # 阻塞 直到收到数据为止
    print("收到来自%s的消息:%s" % (data.decode("utf-8"),addr[0]))
    # 返回值为 数据 和 对方ip地址 和端口号
    server.sendto(data.upper(),addr)

print(res)
server.close()

UDP客户端

import socket

client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)

while True:
    data = input(">>:").encode("utf-8")
    client.sendto(data,("127.0.0.1",8888))
    d,addr = client.recvfrom(1024)
    print(d.decode("utf-8"))

client.close()

半连接池

服务端保存的未完成三次握手的连接的数量,超过一定数量后,再有新的连接请求过来,就不处理了,让请求等待

服务器端模拟

import  socket

server = socket.socket()

server.bind(("127.0.0.1",8888))

# 参数可以设置最大的半连接数   最大5个
server.listen()

import time
while True:
    time.sleep(0.5)
原文地址:https://www.cnblogs.com/shanau2/p/10175111.html