网络编程:python中使用多进程完成UDP通信

有好多人应该好奇QQ通讯聊天的原理吧,底层都是C语言,这是毫无疑问的,因为我们需要C语言去完成底层调动进程。

这里总结一些关于系统编程需要了解的部分知识:
系统编程
多任务编程(同一时间,多个任务同时启动,多任务)
在单核CPU下,电脑只能在同一时刻执行一项任务:
所以在操作系统中,多任务实现的本质就是任务的切换:
1.时间片轮换
2.优先级别调度

多核CPU下,可以存在真正的多任务,就是一个CPU执行一项任务,但这种情况很难实现,因为操作系统本身有许多内置进程

一些概念:
代码:指令的集合。【指一系列人类可读的计算机语言指令】
程序:具有特殊功能代码。【计算任务的处理对象和处理规则的描述】
软件:一系列按照特定顺序组织的计算机数据和指令的集合。
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,
进程是系统进行资源分配和调度的一个独立单位。【计算机中的程序
关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,
是操作系统结构的基础】
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,
它是比进程更小的能独立运行的基本单位。线程自己基本上
不拥有系统资源,只拥有一点在运行中必不可少的资源
(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的
其他的线程共享进程所拥有的全部资源。
协程:不带返回值的函数调用。

进程类的实现:
1.创建一个进程类,要求继承Process类。
创建的类是Process的子类。
2.重写run方法,run方法就是子进程启动进程后需要执行的方法。
3.启动子进程,实例化子进程类的对象,调用start方法。
通过Process或者它的子类来创建进程对象,之后调用start方法启动进程。

守护进程:一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程
在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的
时候才启动吗,完成任务后就自动结束。

使用进程池,批量操作建议是进程池。
CPU密集型(计算密集型):在多重程序系统中,大部份时间用来做计算、
逻辑判断等CPU动作的程序,称为computer bound(CPU bound)。
I/O密集型:有一些进程在input和output上花费了大多时间,称为I/O-bound。
比如搜索引擎蜘蛛(爬取数据)大多数大多数时间是在等待响应这种就
属于I/O密集型。

进程间的通信问题:
1.队列
2.管道
3.管理器
4.信号量
5.套接字编程 (socket)
进程:
本地进程:队列、管道、管理器、信号量
远程进程:网络 socket
使用队列完成本地进程间的通信:
什么是队列?(queue)
队列是一种操作受限制的线性表。
消息管理器(Manager)
它提供很多数据类型,大大的丰富了数据共享的机制,
如list、dictionary、queue、manager等等。

线程和进程的优点和缺点:
线程:内存开销小、并发高、支持数据共享(造成数据不安全)。
进程:内存占有多,安全性高。
Python提供了多线程编程,但一定要使用threading模块,调用的是底层C语言代码,
所以并不是真正意义的多线程。
thread python2常用
threading python3使用
线程从创建到销毁整个过程中,有如下的几种状态:
创建:init new
就绪:ready
运行:run
等待:wait
销毁:destroy
Python的GIL(Global Interpreter Lock):全局解释器锁。
该锁使的CPython解释器无法利用多核的优势。
总结:
在Unix/Linux下,可以使用fork()实现多进程;要实现跨平台的多进程,
可以使用multiprocessing模块。进程间通信是通过Queue、Pipe、Manager等实现的。

在Python开发中,如果要使用多任务,到底选择多线程还是多进程?
CPU 密集型:程序比较偏重于计算,需要经常使用 CPU 来运算。例如科学计算的程序,机器学习的程序等。
I/O 密集型:顾名思义就是程序需要频繁进行输入输出操作。爬虫程序就是典型的 I/O 密集型程序。
如果程序是属于 CPU 密集型,建议使用多进程。而多线程就更适合应用于 I/O 密集型程序。

了解完基础知识,就上代码吧,下面的就是利用os.fork()实现的多进程UDP通信,故只能在Linux/macOS上运行,服务器端和客户端代码一模一样。就是需要注意的发送的和接收的端口,如果是不同的Ubuntu上,这点可以略过。

import os
import socket
#开始的标志,提醒开始聊天
print(“start”.center(30, “-”))
#产生子进程,返回值res,如果res是0,则表示新产生的子进程,另一个 大于0的则是原主进程。
res = os.fork()
#非0的值即为真, if res==true:故省略一部分
if res:
#创建socket对象,AF_INET表示使用IPv4协议通信,SOCK_DGRAM表示使用UDP通信。
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#绑定服务器端的IP
server.bind((“192.168.13.107”, 33335))
try:
while True:
msg = input("请输入>: ")
if msg == “q”:
break
print(“发送出去的消息是:”, msg)
#服务器发送消息,注意发送的消息要编码,目的主机和端口号
server.sendto(msg.encode(“utf-8”), (“192.168.13.107”, 222)

except Exception as e:                                           
    print("出现错误,错误信息是:", e)                                      
finally:                                                         
    server.close()                                               

else:
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.bind((“192.168.13.107”, 33350))
try:
while True:
msg, addr = client.recvfrom(1024)
msg = msg.decode(“utf-8”)
print("\n"+“收到的消息是》》:”, msg)
if msg == “q”:
break
finally:
print(“结束会话”)
client.close()

上面代码只注释一部分,其中res为真的那一部分代码是为了创建socket服务器对象,让原主进程具备发送消息的功能,而else那部分表示的子进程完成信息的接收,这样就具备了接收信息的功能,同时也有发送消息的功能。就好比一个简单的QQ,既能发送消息,又能接收消息 。
如果有什么疑问和不足,可以关注博客,私聊小编,进行改进。风里雨里,墨染离殇都在等你!

Only their own efforts, will be closer to the goal. —— MRIRA

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨染半世离殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值