10 线程 协程 socketserver 基于udp的socketserver

Posted 技术是条不归路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10 线程 协程 socketserver 基于udp的socketserver相关的知识,希望对你有一定的参考价值。

线程进程

操作系统的作用:
1.把硬件丑陋复杂的接口隐藏起来,为应用程序提供良好接口
2.管理,调用进程,并且把进程之间对硬件的竞争变得有序化

多道技术:
1.产生背景:为了实现单cpu下的并发效果
2.分为两部分:
1:空间上的复用(必须实现硬件层面的隔离)
2:时间上的复用(复用cpu的时间片)
什么切换?
1:正在执行的任务遇到的阻塞
2:正在执行的任务运行时间过长

进程:正在运行的一个过程/一个任务,由操作系统负责调用,然后由cpu负责执行
程序:就是程序员写的代码
并发:伪并行,单核+多道
并行:只有多核才能实现真正的并行

同步:打电话,一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行
异步:发短信,一个进程在执行某个任务时,另外一个进程无需等待其执行完毕,就可以继续执行,当有消息返回时,系统会通知后者进行处理,这样可以提高执行效率

进程的创建:
1. 系统初始化
2. 与用户交互
3. 在执行一个进程的过程中调用(Popen,os.fork)
4.批处理任务

系统的调用:
linux:fork
win:CreateProcess

linux的下的进程与windows下的区别:
1:linux的进程有父子关系,是一种树形结构,windows没有这种关系
2:linux创建新的进程需要copy父进程的地址空间,win下从最开始创建进程,两个进程之间就是不一样




线程:一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程
(一个进程内至少一个线程)
进程是资源单位
而线程才是cpu上的执行单位

多线程:一个车间内有多条流水线,多个流水线共享该车间的资源(多线程共享一个进程的资源)

线程创建的开销要远远小于进程

为何要创建多线程?
1. 共享资源
2. 创建开销小

多线程模拟文件编辑器

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-
from threading import Thread
msg_l=[]
format_l=[]
def talk():
    while True:
        msg=input(>>: ).strip()
        if not msg:continue
        msg_l.append(msg)

def format():
    while True:
        if msg_l:
            res=msg_l.pop()
            res=res.upper()
            format_l.append(res)

def save():
    while True:
        if format_l:
            res=format_l.pop()
            with open(db.txt,a,encoding=utf-8) as f:
                f.write(%s\n %res)

if __name__ == __main__:
    t1=Thread(target=talk)
    t2=Thread(target=format)
    t3=Thread(target=save)
    t1.start()
    t2.start()
    t3.start()
多线程模拟文件编辑器

线程对象的其他方法

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-
n=11111111111111111111111111111111111
import time
from threading import Thread
import threading
def work():
    time.sleep(2)
    print(%s say hello %(threading.current_thread().getName()))


if __name__ == __main__:
    t=Thread(target=work)
    # t.setDaemon(True)
    t.start()
    t.join()
    print(threading.enumerate()) #当前活跃的线程对象,是一个列表形式
    print(threading.active_count()) #当前活跃的线程数目
    print(主线程,threading.current_thread().getName())
线程对象的其他方法

单线程实现并发爬取网页

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-
import requests
import time
# response=requests.get(https://www.python.org)
# print(response.status_code)
# print(response.text)

def get_page(url):
    print(GET page:%s %url)
    response=requests.get(url)
    if response.status_code == 200:
        print(response.text)

start_time=time.time()
get_page(https://www.python.org)
get_page(https://www.yahoo.com)
get_page(https://www.github.com)
stop_time=time.time()
print(run time is :%s %(stop_time-start_time)) #11.989685773849487









from gevent import monkey;monkey.patch_all()
import requests
import time
import gevent
def get_page(url):
    print(GET page:%s %url)
    response=requests.get(url)
    if response.status_code == 200:
        print(response.text)

start_time=time.time()
g1=gevent.spawn(get_page,url=https://www.python.org)
g2=gevent.spawn(get_page,url=https://www.yahoo.com)
g3=gevent.spawn(get_page,url=https://www.github.com)
gevent.joinall([g1,g2,g3])
stop_time=time.time()
print(run time is :%s %(stop_time-start_time)) #8.745500326156616
单线程实现并发爬取网页

单线程实现并发的socket服务端

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-
from gevent import monkey;monkey.patch_all()
from socket import *
import gevent
def server(ip,port):
    s = socket(AF_INET, SOCK_STREAM)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    s.bind((ip,port))
    s.listen(5)
    while True:
        conn, addr = s.accept()
        print(client,addr)
        gevent.spawn(talk,conn,addr)

def talk(conn,addr): #通信
    try:
        while True:
            res=conn.recv(1024)
            if not res:break
            print(client %s:%s msg:%s %(addr[0],addr[1],res))
            conn.send(res.upper())
    except Exception:
        pass
    finally:
        conn.close()

if __name__ == __main__:
    server(127.0.0.1, 8080)
单线程实现并发的socket服务端
技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-

from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect((127.0.0.1,8080))

while True:
    msg=input(>>: ).strip()
    if not msg:continue
    c.send(msg.encode(utf-8))
    res=c.recv(1024)
    print(res.decode(utf-8))
客户端

socketserver实现并发

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-

import socketserver
#MyHandler(conn, client_address, s)
class MyHandler(socketserver.BaseRequestHandler): #通讯循环
    def handle(self):
        while True:
            res=self.request.recv(1024)
            print(client %s msg:%s %(self.client_address,res))
            self.request.send(res.upper())

if __name__ == __main__:

    s=socketserver.ThreadingTCPServer((127.0.0.1,8080),MyHandler)
    s.serve_forever() #链接循环
socketserver实现并发

协程

技术分享
import time
def consumer(item):
    # print(item)
    x=111111
    y=22222222222
    z=3333333
    a=abasdfasdfasdfasdfasdf
    b=123213asdfasdfsadfasdf
    pass

def producer(target,seq):
    for item in seq:
        target(item)

start_time=time.time()
producer(consumer,range(100000000))
stop_time=time.time()
print(run time is %s %(stop_time-start_time))






import time
def consumer():
    # print(item)
    x=111111
    y=22222222222
    z=3333333
    a=abasdfasdfasdfasdfasdf
    b=123213asdfasdfsadfasdf
    while True:
        item=yield

def producer(target,seq):
    for item in seq:
        target.send(item)

g=consumer()
next(g)
start_time=time.time()
producer(g,range(100000000))
stop_time=time.time()
print(run time is %s %(stop_time-start_time))
协程
技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-
from gevent import monkey;monkey.patch_all()
import gevent
import time
def eat(name):
    print(%s eat food first %name)
    # gevent.sleep(5)
    time.sleep(5)
    print(%s eat food second % name)
def play(name):
    print(%s play phone 1 %name)
    # gevent.sleep(6)
    time.sleep(6)
    print(%s play phone 2 %name)

g1=gevent.spawn(eat,egon)
g2=gevent.spawn(play,name=egon)
g1.join()
g2.join()
print()
协程gevent(遇到IO自动切换)

 

基于udp的socket

技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-

import socketserver

class MyUDPhandler(socketserver.BaseRequestHandler):
    def handle(self):
        client_msg,s=self.request
        s.sendto(client_msg.upper(),self.client_address)

if __name__ == __main__:
    s=socketserver.ThreadingUDPServer((127.0.0.1,8080),MyUDPhandler)
    s.serve_forever()
多线的udp服务端
技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-

from socket import *
s=socket(AF_INET,SOCK_DGRAM)
s.bind((127.0.0.1,8080))


while True:
    client_msg,client_addr=s.recvfrom(1024)
    print(client_msg)
    s.sendto(client_msg.upper(),client_addr)
服务端
技术分享
#!/usr/bin/python
# -*- coding:utf-8 -*-

from socket import *
c=socket(AF_INET,SOCK_DGRAM)

while True:
    msg=input(>>: ).strip()
    c.sendto(msg.encode(utf-8),(127.0.0.1,8080))
    server_msg,server_addr=c.recvfrom(1024)
    print(from server:%s msg:%s %(server_addr,server_msg))
客户端

 

以上是关于10 线程 协程 socketserver 基于udp的socketserver的主要内容,如果未能解决你的问题,请参考以下文章

python线程进程和协程

socketserver源码解析和协程版socketserver

基于upd的socketserver,即udp的多线程

基于tcp的socketserver,即tcp的多线程

基于socketserver开发多线程ftp

网络编程