前言:
昨天我们已经了解了多进程的原理以及它的实际使用

Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,

但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,

父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程

既然是进程那么就会有运行和退出
接下来我们就来了解一下进程的退出以及处理
 
孤儿进程:
    当父进程于子进程退出,此时子进程就会成为孤儿进程
    特征:
         孤儿进程会被系统指定进程收养,即系统进程成为
 这个孤儿进程新的父进程,系统进程会自动处理进程退出状态
 
僵尸进程:
    当子进程于父进程退出父进程没处理子进程的退出状态
    此时子进程就会成为僵尸进程
    僵尸进程会滞留部分PCB信息在内存中,大量的僵尸进程会消耗系统给的内存资源
    所以要尽量避免僵尸进程的产生
 
如何避免僵尸进程的产生:
    1.父进程先退出
    2.父进程处理子进程状态
 
    PID,status = os.wait
      功能:
         在父进程中阻塞等待处理子进程的退出
      返回值:
           pid :退出的那个子进程PID
   status :子进程的退出状态
      获取原来的退出状态:
             wait(status)
      pid,status = os.waitpid(pid,option)
          功能:在父进程阻塞等待处理子进程的退出
          参数 :
                    pid   -1 表示等待任意子进程退出 
                            >0 表示等待对应PID号的子进程退出 option 
                               0 表示阻塞等待 WNOHANG 表示非阻塞 
          返回值:pid 
                        退出的那个子进程的PID号 status 子进程的退出状态 
 
 
创建二级子进程
  • 父进程创建子进程等待进程退出
  • 子进程创建下一个进程,然后立即退出
  • 二级子进程成为孤儿进程  处理具体工作
 
 
multiprocessing  模块创建进程
  1.需要将要做的事情封装为函数
  2.使用multiprocessing提供的process 创建进程对象
  3.通过进程对象和process初始化进程进行进程的设置绑定函数
  4.启动进程,会自动执行绑定的函数
  5.完成进程的回收
 
创建进程对象:
   process()
     功能:
       创建进程对象
     参数:
       target函数对象
       name 进程称()
       args元组 用来给target函数位置传参
       kwargs字典 用来给target函数键值传参
   p.start()
     功能:
       启动进程自动运行terget绑定函数,
       此时进程被创建
   p.join([timeout])
     功能:
       等待阻塞子进程退出
     参数:超时检测
     如果不使用join回收可能产生僵尸进程
 
  • 使用multiprocessing创建进程子进程同样复制父进程的全部内存空间
  • 之后自己的独立空间 执行互不干扰 子进程也有自己的PID特有资源等
  • 使用multiprocessing创建子进程,一般父进程功能就是创建子进程
  • 回收子进程返回事件交给子进程完成
 
 
 
 
 
 
简单群聊:
 
功能:
  类似QQ群聊
  1.进入聊天室需要输入姓名 姓名不能重复
  2.有人进入聊天室会向其他人发起通知  xxx进入聊天室
  3.如果一个人发消息则其他人都能收到  xxx说:...
  4.如果某个人退出聊天室也会收到通知  xxx退出聊天室
  5.服务端可以喊话:此时群里所有的都能收到服务端消息  管理员说:...
 
 
服务器端:

from socket import *
import os, sys # 发送管理员消息
def do_child(s, addr):
while True:
msg = input("管理员消息:")
msg = "C 管理员 " + msg
s.sendto(msg.encode(), addr) # 用户登录
def do_login(s, user, name, addr):
if (name in user) or name == "管理员":
s.sendto("该用户已存在".encode(), addr)
return
s.sendto(b'OK', addr)
# 通知所有人
msg = "\n欢迎 %s 进入聊天室" % name
for i in user:
s.sendto(msg.encode(), user[i])
# 插入user
user[name] = addr def do_chat(s, user, name, data):
msg = "\n{} 说: {}".format(name, data)
for i in user:
if i != name:
s.sendto(msg.encode(), user[i]) def do_quit(s, user, name):
msg = "\n%s 离开了聊天室" % name
for i in user:
if i == name:
s.sendto(b'EXIT', user[i])
else:
s.sendto(msg.encode(), user[i])
del user[name] # 删除离开的用户 # 接收客户端请求并处理
def do_parent(s):
# 用于存储用户 {'Alex':('127.0.0.1',8888)}
user = {}
while True:
msg, addr = s.recvfrom(1024)
msgList = msg.decode().split(' ')
if msgList[0] == 'L':
do_login(s, user, msgList[1], addr)
elif msgList[0] == 'C':
# "C Levi [I miss you]"
data = ' '.join(msgList[2:])
do_chat(s, user, msgList[1], data)
elif msgList[0] == 'Q':
do_quit(s, user, msgList[1]) # 创建套接字,网络连接,创建父子进程
def main():
# server address
ADDR = ('0.0.0.0', 8888)
# 创建套接字
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR) # 创建父子进程
pid = os.fork()
if pid < 0:
sys.exit("创建进程失败")
elif pid == 0:
do_child(s, ADDR)
else:
do_parent(s) if __name__ == "__main__":
main()
客户端:

from socket import *
import sys, os def login(s, ADDR):
while True:
name = input("请输入用户名:")
msg = "L " + name
s.sendto(msg.encode(), ADDR)
# 接收登录结果
data, addr = s.recvfrom(1024)
if data.decode() == 'OK':
print("@进入聊天室@")
return name
else:
print(data.decode()) # 发送消息
def do_child(s, name, addr):
while True:
text = input("发言(quit退出):")
# 退出
if text.strip() == "quit":
msg = "Q " + name
s.sendto(msg.encode(), addr)
sys.exit("退出聊天室") msg = "C %s %s" % (name, text)
s.sendto(msg.encode(), addr) # 接收消息
def do_parent(s):
while True:
msg, addr = s.recvfrom(1024)
if msg.decode() == 'EXIT':
sys.exit(0)
print(msg.decode() + "\n发言(quit退出):",end="") # main控制套接字的创建
def main():
if len(sys.argv) < 3:
print("argv is error")
return
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST, PORT) s = socket(AF_INET, SOCK_DGRAM) name = login(s, ADDR)
if name:
pid = os.fork()
if pid < 0:
sys.exit("创建子进程失败")
elif pid == 0:
do_child(s, name, ADDR)
else:
do_parent(s)
else:
return if __name__ == "__main__":
main()

Python网络编程(子进程的创建与处理、简单群聊工具)的更多相关文章

  1. Java网络编程Demo,使用TCP 实现简单群聊功能Groupchat,创建一个服务端,使多个客户端都能收到消息

    效果图: 开启服务端 客户端一 客户端二 客户端三 实现代码: 客户端类 import java.io.IOException; import java.net.ServerSocket; impor ...

  2. Java网络编程Demo,使用TCP 实现简单群聊功能GroupchatSimple,多个客户端输入消息,显示在服务端的控制台

    效果: 服务端 客户端 实现代码: 服务端 import java.io.IOException; import java.net.ServerSocket; import java.net.Sock ...

  3. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

  4. 图解Python网络编程

    返回目录 本篇索引 (1)基本原理 (2)socket模块 (3)select模块 (4)asyncore模块 (5)asynchat模块 (6)socketserver模块 (1)基本原理 本篇指的 ...

  5. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

  6. Python 网络编程(一)

    Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

  7. Python学习(22)python网络编程

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

  8. Day07 - Python 网络编程 Socket

    1. Python 网络编程 Python 提供了两个级别访问网络服务: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...

  9. python网络编程-01

    python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...

随机推荐

  1. WPF中TreeView单击展开其子元素以及点击一个元素展开其他元素收起

    TreeView单击展开其子元素: 在WPF的TreeView控件中,要想展开它的子元素,我们必须要鼠标左键点两下或者右键点一下,那么我们怎样实现左键点一下就使它展开呢? Xaml: <Grid ...

  2. nginx缓存批量清除

    研究了一段时间的缓存清除,说说了解的三种方式吧.        1. 原始的只增加缓存模块的,根据访问的路径一条条清除. 根据此方式要进行批量清除的话,必须在设定的缓存目录下通过自己写的程序来读取ng ...

  3. 从Java官网下载JDK1.6等低版本JDK

    今天在浏览Java官网的时候发现旧版本(1.8之前)的JDK安装包下载地址没有在下载页面明显的提供出来.个人通过在官网查看,发现oracle官方将旧版本的JDK全都放在Java Archive模块中了 ...

  4. 使用MongoDB 2.6 C++驱动中的连接池

    .post p{text-indent: 2em;} MongoDB2.6的CXX驱动(mongo-cxx-driver-26compat),内置包含了数据库连接池,方便管理数据库连接,但是官方文档说 ...

  5. Spring Bean依赖但注入(autowired或resource)时NullPointerException(xml和annotation混用的场景下)

    项目中同时使用了xml和annotation的方式管理Spring Bean 启动时候报NullPointerException,依赖注入失败! 参考: http://fly0wing.iteye.c ...

  6. HttpHandler(处理程序) 和 HttpModule(托管模块)

    本文参见:http://www.tracefact.net/Asp-Net/Introduction-to-Http-Handler.aspx 前言:前几天看到一个DTcms网站,里面有个伪静态技术, ...

  7. Excle 常用函数

    1. 查找函数VLOOKUP 使用示例: =VLOOKUP(A1,$C$1:$D$19,2,0) 表示以A1单元格为基准,匹配C1开始到D19的范围数据,在公式行显示D单元格文本,也就是匹配范围的第二 ...

  8. python格式化输出的方式汇总

    %% 百分号标记 #就是输出一个%%c 字符及其ASCII码%s 字符串%d 有符号整数(十进制)%u 无符号整数(十进制)%o 无符号整数(八进制)%x 无符号整数(十六进制)%X 无符号整数(十六 ...

  9. 【shopex】添加网页挂件widgets

    一步步做个widgets 基础篇 首先建立一个目录plugins/widgets/helloword 这个就是新的挂件目录,系统的每个widgets都是一个目录 里面放两个文件: widgets.ph ...

  10. stat.h头文件,轻松获取文件属性

    [以前还为了获取文件的长度,费劲从头读取一遍,一个一个字节的算. 做webserver时候,发现原来stat函数可以返回一个结构,里面包括文件的全部属性. 真是曲折啊.] #i nclude<s ...