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

二.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(b‘hello‘, addr)

server.close()

#客户端
import socket

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

client.sendto(b‘hello server baby!‘, server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)

  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()

三.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()

四.并发编程

  1.操作系统的发展史

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

   手工操作穿孔卡片

   批处理(磁带)

   脱机批处理系统

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

  2.多道技术的产生

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

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

   并发:看上去像同时运行

   多道技术:

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

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

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

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

 

原文地址:https://www.cnblogs.com/majingjie/p/10813430.html

时间: 2024-08-08 08:14:31

DAY 32 UDP协议、Socketserver模块,并发编程基础的相关文章

python 学习_第四模块 并发编程(多线程)

python 学习_第四模块 并发编程(多线程) 1  开启线程方式 from threading import Thread import time def say(name): time.sleep(2) print("%s hello"%name) if __name__ =="__main__": t = Thread(target=say,args=("alex",)) t.start() print("主线程")

python中并发编程基础1

并发编程基础概念 1.进程. 什么是进程? 正在运行的程序就是进程.程序只是代码. 什么是多道? 多道技术: 1.空间上的复用(内存).将内存分为几个部分,每个部分放入一个程序,这样同一时间在内存中就有了多道程序. 2.时间上的复用(CPU的分配).只有一个CPU,如果程序在运行过程中遇到了I/O阻塞或者运行时间足够长.操作系统会按照算法将CPU分配给其他程序使用,依次类推.直到第一个程序被重新分配到CPU会继续运行. 多道技术中的问题解决: 空间复用:程序之间的内存必须分割.这种分割需要在硬件

聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响

Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口.Java内存模型就是这样一个中间层的模型,它为程序员屏蔽了底层的硬件实现细节,支持大部分的主流硬件平台.要理解Java内存模型以及一些处理高并发的技术手段,理解一些基本的硬件知识是必须的.这篇会说一下跟并发编程相关的一些硬件知识. 一个基本的CPU执行计算的过程如下: 1. 程序以及数据被加载到主内存 2. 指令和数据被加载到CPU的高速缓存 3. CPU执行

Java中基于UDP协议的的网络编程(基础篇)

---恢复内容开始--- 一:什么是网络编程? 通俗的来说, 网络编程就是编写程序,让联网的两个或多个设备(例如计算机)之间进行数据传输.Java语言也支持网络编程,JDK提供的 java.net包提供了很多于网络编程相关的类,来支持网络编程方面的学习. 二:java网络编程所使用的协议? 有了计算机网络的基础,我们不难理解,在java中,网络编程是基于网络传输协议的. java网络编程,可以是基于TCP协议的,也可以基于UDP协议的.那么首先我们得知道tcp协议和udp两种协议的区别. 区别:

网络---29 socketserver模块并发 连接合法性

一.socketserver模块 ②服务端 ③客户端 二.连接合法性       ①os.urandom(n) 一种bytes类型的随机生成n个字节字符串的方法 而且每次生成的值都不相同.再加上md5等加密的处理 就能够成内容不同长度相同的字符串了. ②hmac ③ 可见使用hmac和普通hash算法非常类似. hmac输出的长度和原始哈希算法的长度一致. 需要注意传入的key和message都是bytes类型, str类型需要首先编码为bytes. 原文地址:https://www.cnblo

python并发编程基础之守护进程、队列、锁

并发编程2 1.守护进程 什么是守护进程? 表示进程A守护进程B,当被守护进程B结束后,进程A也就结束. from multiprocessing import Process import time ? def task(): print('妃子的一生') time.sleep(15) print('妃子死了') ? if __name__ == '__main__': fz = Process(target=task) fz.daemon = True #将子进程作为主进程的守护进程.必须在

java并发编程基础概念

1.什么是进程和线程 1.1 进程是程序运行资源分配的最小单位 进程是操作系统进行资源分配的最小单位,其中资源包括:CPU.内存空间.磁盘IO等,同一进程中的多个线程共享该进程中的全部系统资源,而进程和进程之间是相互独立的.进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 进程是程序在计算机上的一次执行活动.当你运行一个程序,你就启动了一个进程.显然,程序是死的.静态的,进程是活的.动态的.进程可以分为系统进程和用户进程.凡是用于完成操作

并发编程基础之生产者消费者模式

一:概念 生产者消费者模式是java并发编程中很经典的并发情况,首先有一个大的容器,生产者put元素到 容器中,消费者take元素出来,如果元素的数量超过容器的容量时,生产者不能再往容器中put元素 ,处于阻塞状态,如果元素的数量等于0,则消费者不能在从容器中take数据,处于阻塞状态. 二:示例 /** * */ package com.hlcui.main; import java.util.LinkedList; import java.util.concurrent.ExecutorSe

C++11 并发编程基础(一):并发、并行与C++多线程

正文 C++11标准在标准库中为多线程提供了组件,这意味着使用C++编写与平台无关的多线程程序成为可能,而C++程序的可移植性也得到了有力的保证.另外,并发编程可提高应用的性能,这对对性能锱铢必较的C++程序员来说是值得关注的. 回到顶部 1. 何为并发 并发指的是两个或多个独立的活动在同一时段内发生.生活中并发的例子并不少,例如在跑步的时候你可能同时在听音乐:在看电脑显示器的同时你的手指在敲击键盘.这时我们称我们大脑并发地处理这些事件,只不过我们大脑的处理是有次重点的:有时候你会更关注你呼吸的