1. 程式人生 > >10 線程 協程 socketserver 基於udp的socketserver

10 線程 協程 socketserver 基於udp的socketserver

upper 復用 use style 結構 dto 阻塞 mil 等待

線程進程

操作系統的作用:
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