[python全栈]05.网络编程(4)

目录

  1. epoll方案
  2. 本地套接字
  3. 多任务编程
  4. 进程
  5. 多进程编程

1. epoll方案

使用方法 :基本与poll方法相同
	*将生成对象poll改为epoll()
	*将所有poll对象事件改为epoll事件
poll 和 epoll 的区别 :
	epoll效率要高于 poll 和 select
	epoll的事件触发方式更多
#poll方法事件前加E
#epoll_server.py
from socket import * 
from select import *

#创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(5)

#创建poll对象
p = epoll()

#fileno ---> IO对象的字典
fdmap = {s.fileno():s}

#注册关注的IO
p.register(s,EPOLLIN | EPOLLERR)

while True:
    #进行IO监控
    events = p.poll()
    for fd,event in events:
        if fd == s.fileno():
            c,addr = fdmap[fd].accept()
            print("Connect from",addr)
            #添加新的关注事件
            p.register(c,EPOLLIN | EPOLLHUP)
            fdmap[c.fileno()] = c
        elif event & POLLIN:    
            data = fdmap[fd].recv(1024)
            if not data:
                #客户端退出,从关注事件移除
                p.unregister(fd)
                fdmap[fd].close()
                del fdmap[fd]
            else:
                print(data.decode())
                fdmap[fd].send(b'Receive')

2. 本地套接字

linux 文件分类
b(块设备文件(驱动文件))	c(字符设备文件(字符设备驱动))	d(目录)
 -(普通文件)	l(链接)	s(套接字)	p(管道)

本地套接字:
作用 : 用于本地不同的程序间进行通信
创建流程 : 
	1.创建本地套接字
		sockfd = socket(AF_UNIX,SOCK_STREAM)	#AF_UNIX
	2.绑定本地套接字文件(相当于网络地址)
		#选定文件位置和名称
		#通过bind(path)绑定
		sockfd.bind(path)
	3.监听 listen()
	4.消息收发, recv send

***
os.path.exists(path) 
#功能 : 判断一个文件是否存在
#存在返回 True ; 否则  False
os.remove()
os.unlink()
#功能 :删除一个文件
#参数: 目标文件

接收端(服务端)

#unix_recv.py
from socket import *
import os

#确定套接字文件
sock_file = "./sock_file"

#判断文件是否已经存在
if os.path.exists(sock_file):
	os.remove(sock_file)

#创建本地套接字
sockfd = socket(AF_UNIX,SOCK_STREAM)

#绑定套接字文件
sockfd.bind(sock_file)
#监听套接字
sockfd.listen(3)

#消息收发
while True:
	c,addr = sockfd.accept()
	while True:
		data = c.recv(1024)
		if data :
			print(data.decode())
			c.send(b"Receive")
		else:
			break
	c.close()
sockfd.close()

发送端(客户端)

#unix_send.py
from socket import *

#确保两端使用的是同一个套接字文件
sock_file = "./sock_file"

#创建本地套接字
sockfd = socket(AF_UNIX,SOCK_STREAM)

#连接另一端
sockfd.connect("sock_file")

#消息收发
while  Ture:
	msg = input(">>>")
	if msg :
		sockfd.send(msg.encode())
		print(sockfd.recv(1024).decode())
	else:
		break

sockfd.close()

3. 多任务编程

意义 : 充分利用计算机的资源提高程序的运行效率
定义 : 通过应用程序利用算机的多个核心达到同时执行多个任务的目的
		以此提高计算机的运行效率
实施方案 : 多进程 or 多线程 

并行和并发概念:
并行 : (多核处理器/多线程处理器)多个计算机核心,在同时处理多个任务
		这时多个任务间是并行关系
并发 :同时处理多个任务,内核在多个任务间不断的切换,达到好像都在处理运行的效果
		但实际一个时间点内核只能处理其中一个任务

4. 进程

进程 (Process):
	定义 : 程序在计算机中的一次运行过程
	程序 : 是一个可执行的文件,是静态的,占有磁盘空间,不占有计算机的运行资源
	进程 : 是一个动态过程的描述,占有计算机的资源,有一定的生命周期
	
from time import sleep,ctime
while True:
	sleep(2)
	print(ctime())
	*同一个程序的不同运行过程是不同的进程,占用资源和生命周期都不一样 

进程的创建流程
1. 用户空间通过运行程序或者调用接口发起创建进程
2. 操作系统接受用户请求,开始创建进程
3. 操作系统分配计算机资源,确定进程状态,开辟进程空间等工作
4. 操作系统将创建好的进程提供给应用程序使用

while.py <====> 操作系统(内核) <====> 电脑硬件
和进程相关的概念 :
CPU时间片:
	如果一个进程占有计算机核心,我们称为该进程占有计算机CPU时间片
	*多个任务之间是争夺CPU的关系
	*操作系统决定哪个最终占有CPU
	
PCB(进程控制块)(Processing Control Block)(Linux/Unix)
在内存中开辟的一块空间,用来记录进程的信息
*进程控制块是操作系统查找识别进程的标志

进程信息 : Liunx $ps -aux
PID(Process ID) :
	在操作系统中,每个进程都有一个唯一的ID号,用来区别其他进程
	ID号由操作系统自动分配,是一个大于0的整数
STAT :
S	等待态	(可中断等待)		R	运行态	(包含就绪态)
D	等待态	(不可中断等待)	Z	僵尸进程
T	等待态	(暂停状态)		
------------------------------------------------
<	该进程优先级较高			l	有子进程的
N	该进程优先级较低			s	会话组组长
+	前台进程(当前在终端运行,可以直接交互的进程)
------------------------------------------------
父子进程: 
	在系统中除了初始化进程,每一个进程都有一个父进程,可能有0到多个子进程
	由此形成父子进程关系
查看进程树 :Liunx $pstree
查看父进程的PID :Liunx $ps -ajx	(PPID即为父进程PID)
进程的状态(进程的生命周期) :
*三态 :
	1.就绪态 : 进程具备执行条件,等待系统分配处理器资源
	2.运行/执行态 : 进程占有CPU处于运行状态
	3.等待/阻塞态 : 进程暂时不具备执行条件,阻塞等待,满足条件后再执行

五态 :
	1.新建态 : 创建进程的过程  新建态>>>就绪态
	>>> 三态
	5.终止态 : 执行结束,释放资源  运行/执行态>>>终止态
进程的优先级 :
作用 : 决定了一个进程的执行权限,和占有资源的优先程度
查看进程优先级 : 
	Linux $top	#动态查看系统中的进程信息,用<>翻页
	取值范围 -20 -- 19	-20优先级最高
使用指定的优先级 :
	Linux $nice -9 ./*.py	#以优先级9运行
	Linux $nice --9 ./*.py	#以优先级-9运行 0以下优先级需要sudo运行
	sudo nice --9 ./*.py
进程的特征 : 互不影响 空间独立
	1. 进程之间运行互不影响,各自独立运行
	2. 进程是操作系统资源分配的最小单位
	3. 每个进程空间独立,各自占有一定的虚拟内存
#!/usr/bin/env python3
#修改权限直接运行
# chmod 775 *.py
#./*.py
from time import sleep,ctime
while True:
	sleep(2)
	print(ctime())
#top
什么是进程,进程和程序的区别
了解进程的特征
清楚进程的每种状态,以及状态之间的转换关系

5. 多进程编程

import os
pid = os.fork()
功能 : 创建新的进程
参数 : 无
返回值 : 
	创建失败 : 返回一个负数
	成功 : 在原有进程中返回新的进程的PID号
			在新的进程中返回0
备注 :
	1. 子进程会复制父进程全部代码段,包括fork之前产生的内存空间
	2. 子进程从fork()的下一句开始执行,与父进程互不干扰
	3. 父子进程的执行顺序是不一定的,父子进程公用一个终端显示
	4. 父子进程通常会根据fork()返回值的差异选择执行不同的代码
		所以 if -else 结构几乎是fork()的固定搭配
	5. 父子进程空间独立,操作的都是本空间的内容,互不影响
	6. 子进程也有自己的特性,比如PID号,PCB,命令集等

理解以下运行结果

import os
from time import sleep
print("***************")
a=1

pid = os.fork()

if pid < 0:
    print("create new process failed")
if pid == 0 :
    print("this is new process")
    print("a=",a)
    a = 10000
else:
    sleep(1)
    print("this is original process")
    print("parent a = ",a)

print("over")

###>>>
***************
this is new process
a= 1
show_over
this is original process
parent a =  1
over
进程相关函数

os.getpid()
功能 : 获取当前进程的进程号
返回值 : 返回进程号
os.getppid()
功能 : 获取当前进程父进程的PID号
返回值 : 返回进程号
import os
pid = os.fork()
if pid < 0 :
    print("Error:create a new process failed")
elif pid == 0 :
    print("C>>>Child pid: ",os.getpid())
    print("C>>>Father pid",os.getppid())
else:
    print("F>>>Child pid: ",pid)
    print("F>>>Father id",os.getpid())
#>>>
F>>>Child pid:  15002
F>>>Father id 15001
C>>>Child pid:  15002
C>>>Father pid 15001
进程退出
os._exit(status)
功能 : 进程退出
参数 : 进程的退出状态
		一般写自然数
父进程可以查看子进程的退出状态

sys.exit([status])
功能 : 进程退出
参数 : 数字表示退出状态,不写默认0
		字符串,表示退出时打印的内容
*sys.exit() 可以通过捕获 SystemExit 异常阻止退出

import os,sys
#结束进程后不再执行后面的内容
#os._exit(0)
try:
    sys.exit("sys.exit worked")
except SystemExit as e:
    print("exit:",e)
print("process exit")
#>>>
exit: sys.exit worked
process exit
孤儿进程和僵尸进程
孤儿进程 : 
	1.父进程先于子进程退出
		此时子进程就会成为孤儿进程
	
	*孤儿进程会被操作系统指定的进程收养
		系统进程就会成为孤儿进程新的父进程
	*孤儿进程不会成为僵尸进程,会被新的父进程处理退出状态

僵尸进程 :
	1.子进程先于父进程退出 2.但是父进程没有处理子进程的退出状态
		此时子进程就会成为僵尸进程

	*僵尸进程会存留少量PCB信息在内存中,大量僵尸进程会消耗系统资源
		应该避免僵尸进程产生

以下程序子进程成为僵尸进程

import os
from time import sleep

pid = os.fork()

if pid < 0:
    print("create process failed")
elif pid == 0:
    print("Child process",os.getpid())
    print("Child process exit")
else:
    print("parent process")
    while True:
        pass
写一个聊天室,功能类似QQ群聊
1. 进入聊天室需要输入姓名,姓名不能重复
2. 有人进入聊天室会向其他人发送通知: ***进入聊天室
3. 一个人发消息,其他人会收到消息: ***说:#######
4. 某人退出聊天室,其他人也会收到通知: ***退出了聊天室

服务端	客户端
*使用什么技术
*知识点回归复习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值