DAY 32 UDP协议Socketserver模块,并发编程基础

Posted majingjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DAY 32 UDP协议Socketserver模块,并发编程基础相关的知识,希望对你有一定的参考价值。

一.粘包现象

  1.为什么会出现粘包现象

    1.只有在TCP协议中才会出现粘包现象,因为TCP协议是流式协议

    2.TCP协议的特点是将数据量小、时间间隔比较短的数据一次性打包发送

    3.粘包现象的本质是因为不知道需要接受的数据的长短

  2.如何解决粘包问题

    1.发送数据直接先告诉对方数据量的大小

    2.利用struct模块定制我们自己的消息传输协议

  3.基于TCP发送大文件示例

技术图片
# 客户端
import struct
import json
import socket
import os

client = socket.socket()
client.connect((127.0.0.1, 8080))

file_size = os.path.getsize(r/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4)
file_path = r/Users/jiboyuan/PycharmProjects/aboutsocket/10 解决粘包问题终极版.mp4
data_dic = {
    file_name: 澳门最大线上赌场开业啦.mp4,
    file_size: file_size
}
header_json = json.dumps(data_dic)
header_bytes = header_json.encode(utf-8)
# 制作字典的报头
header = struct.pack(i, len(header_bytes))
# 发送报头
client.send(header)
# 发字典数据
client.send(header_bytes)
# 打开文件发送文件数据
with open(file_path,rb) as f:
    for line in f:
        client.send(line)

# 服务端
import socket
import json
import struct

server = socket.socket()
server.bind((127.0.0.1, 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            header = conn.recv(4)
            if len(header) == 0:break
            dic_len = struct.unpack(i, header)[0]

            real_dic = json.loads(conn.recv(dic_len).decode(utf-8))
            print(real_dic)
            file_name = real_dic.get(file_name)
            file_size = real_dic.get(file_size)
            recv_size = 0
            with open(file_name, wb) as f:
                while recv_size < file_size:
                    recv_data = conn.recv(1024)
                    f.write(recv_data)
                    recv_size += len(recv_data)
        except ConnectionResetError:
            break
View Code

二.UDP协议

  1.UDP协议的优点

   1.UDP协议客户端允许发空

   2.UDP协议不会粘包

   3.UDP协议服务端不存在的情况下,客户端照样不会报错

   4.UDP协议支持并发

  2.UDP协议的要求

   1.UDP协议也叫数据报协议,发送的消息都带有数据头

   2.UDP的服务端不需要进行监听也不需要建立连接

   3.服务端启动后只能被动的等待客户端发送消息,发送消息时要带上服务端地址

   4.服务端在回复消息的时候,也需要带上客户端的地址、

  示例:

技术图片
# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind((127.0.0.1, 8080))

msg, addr = server.recvfrom(1024)
print(msg.decode(utf-8))
server.sendto(bhello, addr)

server.close()

#客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = (127.0.0.1, 8080)

client.sendto(bhello server baby!, server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)
View Code

  3.UDP协议特点

   1.无链接,类似于发短信,发了就行爱回不回没有任何关系

   2.将服务端关闭,客户端依旧能够发数据,不需要考虑服务端能不能收到

  4.基于UDP实现简易版本QQ

技术图片
# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind((127.0.0.1, 8080))
while True:
    msg, addr = server.recvfrom(1024)
    print(addr)
    print(msg.decode(utf-8))
    info = input(>>>:).encode(utf-8)
    server.sendto(info, addr)

server.close()

# 多个客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = (127.0.0.1, 8080)

while True:
    info = input(>>>:)
    info = (来自客户端1的消息:%s%info).encode(utf-8)  # 改中文备注即可
    client.sendto(info, server_addr)
    msg, addr = client.recvfrom(1024)
    print(msg.decode(utf-8), addr)

client.close()
View Code

三.socketserver模块(让TCP也能支持并发)

技术图片
# TCP socketserver使用
import socketserver
class MyTcpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                data = self.request.recv(1024)  # 对于tcp,self.request相当于conn对象
                if len(data) == 0:break
                print(data)
                self.request.send(data.upper())
            except ConnectionResetError:
                break
if __name__ == __main__:
    server = socketserver.ThreadingTCPServer((127.0.0.1,8081),MyTcpServer)
    server.serve_forever()

# UDP socketserver使用
import socketserver


class MyUdpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data, sock = self.request
            print(data)
            sock.sendto(data.upper(), self.client_address)


if __name__ == __main__:
    server = socketserver.ThreadingUDPServer((127.0.0.1, 8080), MyUdpServer)
    server.serve_forever()
View Code

四.并发编程

  1.操作系统的发展史

   输入输出设备>>>:IO操作即(input和output)

   手工操作穿孔卡片

   批处理(磁带)

   脱机批处理系统

   一步步的优化,其实都是在提高计算机CPU利用率的问题(问题在于时串行并且没有空间上的复用)

  2.多道技术的产生

   解决cpu在执行程序,遇到io时,不干活的情况

   串行:一个程序完完整整的运行完毕,才能运行下一个程序

   并发:看上去像同时运行

   多道技术:

    1.空间上的复用(多个程序共一套硬件设备,它是多道技术实现时间上的复用的基础,不然还要去硬盘读数据)

    2.时间上的复用(单个cpu的电脑上,起多个应用程序。cpu快速切换,给人的感觉是同时运行)

    3.一个任务占用cpu时间过长或被操作系统强行剥夺走cpu的执行权限(比起串行效率反而降低)

    4.一个任务执行过程中遇到io操作,也会被操作系统强行剥夺走cpu的执行权限(比起串行效率提高)

 

以上是关于DAY 32 UDP协议Socketserver模块,并发编程基础的主要内容,如果未能解决你的问题,请参考以下文章

基于UDP协议的socket套接字编程 基于socketserver实现并发的socket编程

UDP协议

Python-网编汇总socketserver

网络编程- socket协议小结hmac的检验客户端合法性和socketserver模块

python 2.7中有没有socketserver这个模块

Socket编程,SocketServer模块