网络编程(六)

前情回顾:waitpid 创建二级子进程

注意事项:先根据功能计划模块,确定技术点做好整体架构的设计模块的编写 ----》 模块的测试发现bug或者进行优化积累调试经验

multiprocessing 

Process(name,target,args,kwargs) ---》 进程对象pp.pid  p.name  p.start()  p.join()  p.is_alive()p.daemon

文件拷贝

cookie :size = os.path.getsize(‘file‘)功能:获取一个文件的大小

************************************************创建自己的进程类

class Parent(object):    #固定方法,希望父类给实现好      def __call__():            run(1,2,3)

def run(a,b,c):            pass 

class Child(Parent):      def __call__():            run(1,2,3)

def run(a,b,c):          ....            ....

多进程 优点 : 并行多个任务,提高运行效率        空间独立,数据安全,创建方便

缺点 : 进程创建销毁的过程中消耗较多的计算机资源

进程池

在需要频繁的创建删除较多进程的情况下,导致计算机资源消耗过多

进程池如何处理 1. 创建进程池,在池内放入适量的进程2. 将事件加入进程池等待队列3. 使用进程池中的进程不断处理事件4. 所有事件处理后,回收关闭进程池

from multiprocessing import Pool 

Pool()功能 : 创建进程池参数 : processes : 指定进程池中进程数量返回 : 得到进程池对象

pool.apply_async() 功能 : 异步方式将事件放入进程池执行参数 : func : 要执行的事件函数        args : 同Process中args 给函数传参            kwds : 同Process中kwargs 给函数传参返回值 : 返回一个对象 该对象可以通过get()方法得到           func函数的返回值

pool.close() 功能 : 关闭进程池,使其无法加入新的事件pool.join()功能 : 阻塞等待进程池退出 (当所有事件处理完毕后)

pool.apply() 用法和apply_async一样,只是需要顺序执行,一个事件结束在执行另一个事件

pool.map(func,iter)功能 : 类似于内建函数map 将第二个参数的迭代数传递个第一个参数的函数执行。同时兼容了使用进程池执行返回值: 返回func的返回值列表

r = pool.map(fun,test)===>

r = []for i in test:   res = pool.apply_async(fun,(i,))   r.append(res.get())

进程间通信

磁盘交互 : 1. 速度慢            2. 不安全

socket    本地套接字

管道  消息队列  共享内存  信号   信号量  套接字

管道通信  pipe

在内存中开辟一块空间,对多个进程可见,通过管道,多进程进行通信

multiprocessing --- 》 Pipe

fd1,fd2 = Pipe(duplex = True)功能 : 创建一个管道参数 : duplex 默认为True  表示双向管道        设置为False 则表示单向管道返回值 : 返回两个管道流对象,表示管道的两端         如果是双向管道则连个均可读写             如果为单向管道则,fd1只能读,fd2只能写

fd1.recv()功能 : 接收消息 (每次接收一条)参数 : 无返回值: 接收到的消息

* 如果管道没有消息会阻塞

fd2.send(data) 功能 : 发送消息  可以是字符串或其他类型 参数:要发送的内容

* 如果没有接收端则管道破裂

消息队列 

队列 : 先进先出

在内存中开辟队列模型,用来存放消息。认可拥有队列的进程都可以存取消息

创建队列 q = Queue(maxsize = 0)功能 : 创建一个消息队列参数 : maxsize 默认为0 表示队列可存放消息由内存而定                     > 0  表示队列最多存放多少条消息返回值 : 返回消息队列对象

q.put()  功能 : 向队列中存放消息 参数 : 要存的消息 (字符串 整数 列表)* 当队列满时会阻塞 

q.full()判断队列是否为满  满返回True

q.get()功能 : 向队列中取出消息 返回值 :取出的消息* 当队列空时会阻塞

q.empty()判断队列是否为空  空返回True

q.qsize()得到当前队列中消息的个数

q.close() 关闭队列

* put  get中均有可选参数 block 和timeoutblock 默认为True 表示阻塞函数 如果设置为False则不阻塞timeout  block 为True 时 设置超时时间

共享内存 

在内存中开辟一段空间,存储数据,对多个进程可见。每次写入共享内存的数据会覆盖之前的内容。由于对内存格式化较少,所以存取速度快

from multiprocessing import  Value,Array

obj = Value(ctype,obj)功能 : 开辟共享内存空间参数 : ctype  str  要转变的c类型 (对照ctype表)        obj  写入共享内存的初始值返回值 : 返回一个共享内存对象

obj.value 即可得到共享内存中的值

obj = Array(ctype,obj)功能 : 开辟共享内存空间参数 : ctype  要转换的类型        obj    存入到共享内存中的数据                   是一个列表,要求列表中数类型一致               正整数,则表示开辟一个多大的序列空间

返回值: 返回一个共享内存对象

管道        消息队列       共享内存开辟空间   内存         内存          内存

读写方式  双向/单向    先进先出      操作覆盖内存

效率      一般         一般            快

应用     多用于亲      方便灵活       较复杂          缘进程        广泛

是否需要   否           否            需要互斥机制

信号 一个进程向另一个进程通过信号传递某种讯息

kill  -l  查看信号kill   -signame  PID   给PID的进程发送一个信号

关于信号:

信号名称 : 系统定义,信号的名字  信号的含义  : 系统定义 ,信号的作用 信号的默认处理方法 : 系统定义,信号给接收进程带来的行为 一般有  终止  暂停  忽略

python 如何操作信号 

发送os.kill(pid,sig)功能:向一个进程发送一个信号参数 : pid : 要发送信号的进程PID        sig : 要发送的信号

signal.alarm(sec)功能 : 向自身发送一个时钟信号 SIGALRM参数 : sec 时钟秒数

* 信号属于异步通信方式,信号的发送不会影响进程的持续执行

*一个进程中只能同时有一个时钟,后面的时钟时间会覆盖前面的

处理 : 

signal.pause() 功能: 阻塞等待一个信号的发生

作业: 1. 对进程间通信方式进行描述连接2. 熟悉进程间通信代码

**********************************************************import signal import time 

#3秒后向自己发送个SIGALRM信号signal.alarm(3)time.sleep(2)

signal.alarm(8)

#阻塞等待接收一个信号signal.pause()

while True:    time.sleep(1)    print("等待时钟.....")**********************************************************from multiprocessing import Array,Process import time 

def fun(shm):    for i in shm:        print(i)    shm[2] = 1000

#开辟共享内存空间,可容纳6个整数#初始值是[1,2,3,4,5,6]# shm = Array(‘i‘,[1,2,3,4,5,6])#表示在共享内存中开辟一个包含6个整形的空间shm = Array(‘i‘,6)

p = Process(target = fun,args = (shm,))p.start()p.join()for i in shm:    print(i)**********************************************************from multiprocessing import Process import time 

class ClockProcess(Process):    def __init__(self,value):        self.value = value        Process.__init__(self)

# 在自定义的进程类中 重写父类的这个方法    def run(self):        n = 5        while n > 0:            print("The time is {}".\                format(time.ctime()))            time.sleep(self.value)            n -= 1

#用自己的进程类创建进程p = ClockProcess(2)

# 自动执行run方法p.start()p.join()***********************************************************import os from multiprocessing import Process 

#获取文件大小size = os.path.getsize(‘file.jpg‘)

# 在创建进程前获取文件对象,父子进程操作同一个文件流# 会造成操作混乱# f = open(‘file.jpg‘,‘rb‘)

#复制前半部分def copy1():    f = open(‘file.jpg‘,‘rb‘)    n = size // 2    fw = open(‘copy1.jpg‘,‘wb‘)    while True:        if n < 64:            data = f.read(n)            fw.write(data)            break        data = f.read(64)        fw.write(data)        n -= 64    fw.close()

#复制后半部分def copy2():    f = open(‘file.jpg‘,‘rb‘)    fw = open("copy2.jpg",‘wb‘)    f.seek(size //2,0)    while True:        data = f.read(64)        if not data:            break        fw.write(data)    fw.close()

p1 = Process(target = copy1)p2 = Process(target = copy2)

p1.start()p2.start()

p1.join()p2.join()*****************************************************import os import signal 

#向24051进程发送SIGKILL信号os.kill(24051,signal.SIGKILL)*****************************************************from multiprocessing import Process,Pipe import os,time 

#如果参数为False则fd1只能recv  fd2只能send# fd1,fd2 = Pipe(False)

#创建一个双向管道fd1,fd2 = Pipe()# fd1.close()

def fun(name):    time.sleep(3)    #发字符串到管道    fd2.send("hello " + str(name))    print(os.getppid(),"----",os.getpid())

jobs = []

for i in range(5):    p = Process(target = fun,args = (i,))    jobs.append(p)    p.start() 

#接收子进程发送的消息for i in range(5):    data = fd1.recv()    print(data) 

for i in jobs:    i.join()*******************************************************from multiprocessing import Pool from time import sleep import os 

def worker(msg):    sleep(2)    print(msg)    return msg + " over"

# 创建进程池pool = Pool(processes = 4)

result = []# 放入事件for i in range(10):    msg = "hello %d"%i     #加入事件后进程就会立即操作事件    #apply_async 的返回值对象,该对象可以获取worker返回结果    r = pool.apply_async(worker,(msg,))    # pool.apply(worker,(msg,))    result.append(r)

# sleep(3)# print("++++++++")#关闭进程池 不能再加入事件pool.close() # sleep(3)# print("*********") #阻塞等待回收pool.join()

print("===========")#通过apply_async()返回对象get()方法获取返回值for res in result:    print(res.get())********************************************************from multiprocessing import Pool import time 

def fun(fn):    time.sleep(1)    return fn * fn  

test = [1,2,3,4,5,6]

pool = Pool(processes = 4)#使用map迭代r = pool.map(fun,test)print(r)pool.close()pool.join()***********************************************************from  multiprocessing import Queue from time import sleep#创建队列q = Queue(3) 

q.put(1)print(q.full())q.put(2)q.put(3)print(q.full())

# 设置超时事件为3sec# q.put(4,True,3)

print(q.get())print("队列中还有%d条消息"%q.qsize())print(q.empty())q.close() #关闭队列*************************************************************from multiprocessing import Process,Queue import time 

#创建消息队列q = Queue()

def fun1():    time.sleep(1)    q.put("我是进程1")

def fun2():    time.sleep(2)    print("取消息:",q.get())

p1 = Process(target = fun1)p2 = Process(target = fun2)p1.start()p2.start()

p1.join()p2.join()***************************************************************from multiprocessing import Value,Process import time import random 

#向共享内存存钱def deposite(money):    for i in range(100):        time.sleep(0.03)        money.value += random.randint(1,200)#从共享内存取钱def withdraw(money):    for i in range(100):        time.sleep(0.02)        money.value -= random.randint(1,150)

#创建共享内存对象money = Value(‘i‘,2000)

d = Process(target = deposite,args = (money,))w = Process(target = withdraw,args = (money,))d.start()w.start()d.join()w.join()

print(money.value)***************************************************************import os import time 

while True:    time.sleep(2)    print(os.getpid()) ***************************************************************

原文地址:https://www.cnblogs.com/wcin/p/9119054.html

时间: 2024-10-16 17:03:15

网络编程(六)的相关文章

iOS网络编程(六) NSURLSession详解

昨夜浏览Demo的时候,看到别人请求网络数据用的是NSURLSession,当时就在想这里什么,怎么没有用过,引起了我的好奇心,遂去百度-谷歌-官方文档一一查看,有了一定的了解,原来NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的. 查找资料,写了一个小Demo,大家可以看看,有什么不足的地方,可以留言帮我指出来. // // HMTRootViewController.m // // // Created by HMT on 14-6-7.

Unix网络编程(六)高级I/O技术之复用技术 select

I/O复用技术 本文将讨论网络编程中的高级I/O复用技术,将从下面几个方面进行展开: a. 什么是复用技术呢? b. 什么情况下需要使用复用技术呢? c. I/O的复用技术的工作原理是什么? d. select, poll and epoll的实现机制,以及他们之间的区别. 下面我们以一个背景问题来开始: 包括在以前的文章中我们讨论的案例都是阻塞式的I/O包括(fgetc/getc, fgets/gets),即当输入条件未满足时进程会阻塞直到满足之后进行读取,但是这样导致的一个 问题是如果此时进

Linux 网络编程六(多进程服务器僵尸进程解决方案)

僵尸进程解决方案 1.忽略SIGCHLD信号,这样不会出现僵尸进程 2.安装信号,父进程接收到SIGCHLD信号后,wait()子进程 注意:这里的客户端有两个进程,一个接收信息,一个发送信息,当客户端退出时,会将sockfd套接字关闭两次 //头文件 int server_socket(); int client_socket(); //服务器端 #include "pub.h" int main(int arg,char *args[]) { server_socket(); re

网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门

1.前言 即时通讯网整理了大量的网络编程类基础文章和资料,包括<TCP/IP协议 卷1>.<[通俗易懂]深入理解TCP协议>系列.<网络编程懒人入门>系列.<不为人知的网络编程>系列.<P2P技术详解>系列.<高性能网络编程>系列.甚至还有图文并貌+实战代码的<NIO框架入门>等,目的是帮助即时通讯类应用的开发者,至少要掌握网络编程最基本的原理,所谓知其然更要知其所以然.尤其现在移动网络大行其道的时代,在网络环境如此复杂的

[转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么? http://www.52im.net/thread-1732-1-1.html 1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机网络编程的基础,TCP/UDP收发消息都靠它.我们熟悉的web服务器底层依赖它,我们用到的MySQL关系数据库.Redis内存数据库底层依赖它.我们用微信和别

[转帖]脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手 http://www.52im.net/thread-1729-1-1.html 1.引言 网络编程中TCP协议的三次握手和四次挥手的问题,在面试中是最为常见的知识点之一.很多读者都知道"三次"和"四次",但是如果问深入一点,他们往往都无法作出准确回答. 本篇文章尝试使用动画图片的方式,来对这个知识点进行"脑残式"讲解(哈哈),期望读者们可以更加简单.直观地理解TCP网络通信交互的本

网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步发布于:http://www.52im.net/thread-2067-1-1.html) 2.关于作者 翟志军,个人博客地址:https://showme.codes/,Github:https://github.com/zacker330.感谢作者的原创分享. 作者的另一篇<即时通讯安全篇(七)

六星经典CSAPP-笔记(11)网络编程

六星经典CSAPP-笔记(11)网络编程 参照<深入理解计算机系统>简单学习了下Unix/Linux的网络编程基础知识,进一步深入学习Linux网络编程和TCP/IP协议还得参考Stevens的书. 1.网络基础 (略过,待补充) 2.IP地址 2.1 IP地址的表示 IP地址是一个无符号的32位整数.Linux网络程序使用下面这种IP地址结构存储IP地址: /* Internet address structure */ struct in_addr { unsigned int s_add

网络编程(六):端口那些事儿

TCP和UDP协议都存在一个叫做端口的东西,但端口却不是IP协议的一部分. 端口被设计出来主要是为了给协议栈和应用对应: 协议栈用端口号将数据分配给不同的应用层程序 应用层程序用端口号去区分不同的连接,参见之前提到过的"四元组" TCP和UDP协议都使用了端口号(Port number)的概念来标识发送方和接收方的应用层. 对每个TCP连接的一端都有一个相关的16位的无符号端口号分配给它们. 即使是UDP这种没有连接的协议,依旧有一个16位的无符号端口号. 可能的.被正式承认的端口号有