网络编程

一、#socketserver 实现并发处理。对socket的再封装。
#overding 覆盖 request 请求 handle 处理 subclass 继承 instantiate 实例化
#handle_request 只处理一个请求 server_forever 处理多个请求,永远执行
#定义重写handler方法类 handler 自己处理所有于客户端的交互
#
#实例化TCPSERVER

import socketserver

class MyTcpHandler(socketserver.BaseRequestHandler):

def handle(self):
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote".format(self.client_address[0]))
print(self.data)
if not self.data: #客户端断开处理
print(self.client_address,"断开了")
break
self.request.sendall(self.data.upper())
except ConnectionResetError as e:
print('error:',e)
break
if __name__ == '__main__':
HOST,PORT = "localhost",9999
server = socketserver.TCPServer((HOST,PORT),MyTcpHandler)
# 更换为ThreadingTCPServer,实现了多线程并发
#server = socketserver.ThreadingTCPServer((HOST,PORT),MyTcpHandler)
# 多进程并发
#server = socketserver.ForkingTCPServer((HOST,PORT),MyTcpHandler)

server.serve_forever()

2、
#socketserver 实现并发处理。对socket的再封装。
#overding 覆盖 request 请求 handle 处理 subclass 继承 instantiate 实例化
#handle_request 只处理一个请求 server_forever 处理多个请求,永远执行
#定义重写handler方法类 handler 自己处理所有于客户端的交互
#
#实例化TCPSERVER

import socketserver

class MyTcpHandler(socketserver.BaseRequestHandler):

def handle(self):
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote".format(self.client_address[0]))
print(self.data)
if not self.data: #客户端断开处理
print(self.client_address,"断开了")
break
self.request.sendall(self.data.upper())
except ConnectionResetError as e:
print('error:',e)
break
if __name__ == '__main__':
HOST,PORT = "localhost",9999
# 更换为ThreadingTCPServer,实现了多线程并发
server = socketserver.ThreadingTCPServer((HOST,PORT),MyTcpHandler)

server.serve_forever()

3、
多线程、多进程
线程:thread
操作系统能够进行运算调度的最小单位,是一串指令的集合
它包含在进程当中

进程:::process
每个程序的内存是独立的,暴露给操作系统的是一个整体的、可管理的程序,就是进程,
说白了就是QQ,画图之类的都是进程,里面包含对个中资源的调用、内存的管理、网络接口的调用,对各种资源管理的集合,即为进程

进程要操作cpu,必须要先创建一个线程,

进程与线程的区别
1、线程共享内存空间,进程的内存是独立的
2、同一个进程的线程之间可以直接交流,但两个进程想要通信,必须通过一个中间代理来实现
3、创建新的线程很简单,创建新的进程需要对其父进程进行一次克隆
4、一个线程可以控制与操作同一进程下的其他线程,但进程只能操作子进程
5、更改主线程可能对其他线程有影响,但更改父进程对进程无任何影响



'''不加join ,主线程不依赖与子线程的执行完成,为并行关系,等待所有线程结束 主进程就执行结束,程序退出;
加了join ,则主线程需要等子线程执行完成
不加join 并且将 线程设置为守护线程,则主线程执行完毕,只管非守护线程执行完毕,就退出了,守护线程则不需要管,哪怕其中有sleep2000秒
守护线程
以本例子中的为例,当子线程变成守护线程了,则主线程执行自己完毕即可,不会等待子线程的2秒结束,程序自动退出
!!!主线程退出时,守护线程监测到主线程关闭,则自动关闭

应用场景:socketserver,每一个连接进入则启动一个新线程,如果将socketserer停止,则不需要等子线程结束,就自动结束
'''

'''
GIL 全局解释器锁 ,PYTHON的线程是调用操作系统的原生线程(C语言的接口),

interperter 解释器
lock = threading.Lock() #3.0里默认存在 ,但是python是假的多线程(CPU不断切换线程上下文),
对于多个线程操作相同内存的情况,可能造成数据混乱,故需要使用锁可能有这种情况的添加上(此时该部分属于串行,非多线程并行)
'''
信号量 :semaphore
aa= threading.Boundsemaphore(5) 开启5个并行线程
在处理中,使用 aa.acquire() aa.release 来确定并行


''' 事件event
通过标志位,实现线程的的事件,来实现两个线程之间的交互
event = threading.Event()
event.set() 设置标志位
event.clear() 清空标志位
event.is_set() 监测是否设置标志位
event.wait() 等待标志位设置
'''
队列 的作用:
1、程序的解耦
2、提高效率

queue Queue 先入先出
lifoQueue 后入先出
PriorityQueue 设置优先级 数字越小越优先
taskdown
生产者消费者模型,通过queue实现,表现了队列的作用

4、
ssh
公钥 public key

私钥 private ket

自己拿着私钥 ,把公钥给别人,然后就可以从 自己的主机连接别人的主机(不需要密码)

192.168.0.13--->192.168.0.11
私钥 公钥

如何生成 ?执行下面命令,在该用户根目录下的.ssh目录下生成了id_ras(私钥), id_ras.pub,将公钥内容拷贝至客户机用户的.ssh 目录下的authorized_keys 中,即可实现
ssh-keygan

也可以通过
ssh-copy-id "-p22 root@192.169.0.11"
实现将公钥放至客户机对应用户的根目录的.ssh/authorized_keys 中
---不同的操作系统命令有所不同

import paramiko
'''该传送文件主要是模拟ssh的scp命令来实现文件传输'''

#创建传输连接,连接服务器
transport = paramiko.Transport(('192.168.0.11',22))
#使用用户名密码连接的形式
#transport.connect(username='root',password='73409')
#使用公钥私钥对连接
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')
transport.connect(username='tomcat',pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
#将本地文件上传至服务器
#sftp.put('paramiko-1.py','/tmp/test.py')
#将远程文件下载到本地目录
sftp.get('/home/tomcat/apache-tomcat-7.0.82.tar','tomcat.tar')
transport.close()

5、
1、进程的使用方法和线程类似
import multiprocessing

p = multiprocessing.Porcess(target=function,args=('111',))
p.start()
p.join()

2、进程之间互相通信(父进程和子进程) 进程的Queue方法
父进程通过调用进程的Queue方法创建一个Queue,创建子进程时复制了该Queue,然后子进程向自己本身的Queue放数据,
父子进程的Queue之间的内部同步机制,使得看起来父进程消费了子进程的Queue上的数据。实际上是内部机制所致。

3、管道实现通信数据传递Pipe
特性:父子管道进行通信,均可收发数据,多收了数据会等待

4、manager
特性:通过内部锁,控制每次只有一个进程操作数据,同样是通过复制的方式,完成数据的共享及修改。

5、进程池 Pool
apply 串行
apply_async() 并行

__name__ == '__main__' 的含义是,当执行本脚本时执行该内容,当 作为模块调用时,__name__为其他的,不执行该部分内容




5、协程
协程 又称为微线程,简单来说,协程是一种用户态的轻量级的线程
协程溶有自己寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来时,回复先前保存的寄存器上下文和栈。
因此: 协程能保留上一次调用时的状态(即所有局部状态的一个特定组合)。每次过程重入时,进入上一次调用时的状态。
协程的好处:
1、无需线程上下文切换的开销
2、无需原子操作及同步开销(线程修改变量即是一个原子操作)
3、方便切换控制留,简化编程模型
4、高并发+高扩展性+低成本,一个CPU支持上万的协程不是问题,适合高并发处理
缺点:
1、无法利用多核资源
2、需要和进程配合才能运行在多CPU上
3、运行阻塞(Blocking)操作(如IO时)会阻塞到整个程序

协程为何单线程并行的情况下实现多并发,主要原则就是遇到IO操作就切换,什么时候开始切换,什么时候切回去是如何实现的?


论事件驱动及异步IO
编写服务器处理模型的程序时,每收到一个请求,放入事件列表中,让主进程通过非阻塞I/O方式来处理请求

事件驱动模型 ,很多的UI平台都会提供OnClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:
1、有一个消息(事件)队列;
2、当鼠标按下时,往这个队列里增加一个事件(消息)
3、有个循环,不断从队列中取出事件,调用不同函数进行处理
4、事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数


同步IO ----阻塞IO 非阻塞IO 多路复用IO
异步IO


IO请求分为两步:1、用户程序向内核请求数据,内核是否收到数据,未收到,阻塞
2、内核收到数据,向用户程序应用发送数据 此过程默认阻塞

a、单线程1、2 均阻塞 阻塞IO,
b、单线程多次请求是否收到数据,2阻塞, 非阻塞IO
c、多个请求,当一个收到数据时接收,1不阻塞,2 阻塞
d异步IO,用户程序发起请求,然后处理其他事情,内核收到数据并发送到用户程序后通知用户程序数据已发送

IO多路复用 select poll epoll
select poll 缺点

epoll 支持水平触发和边缘触发
水平触发,内核通知数据来了,用户不取,下次仍通知
边缘触发,内核通知数据来了,用户不取,下次不通知
原文地址:https://www.cnblogs.com/yunzaixiao/p/8260780.html