1.UDP套接字
注意:
udp是無鏈接的,先啟動(dòng)哪一端都不會報(bào)錯(cuò)
因?yàn)閡dp協(xié)議無連接,所以發(fā)送數(shù)據(jù)格式為client.sendto(消息內(nèi)容,服務(wù)器IP與端口的元組)
接收數(shù)據(jù)格式:data,client_addr=server.recvfrom(1024)
data為接收到的數(shù)據(jù),client_addr為發(fā)送者的IP與端口的元組,用以回復(fù)消息
因?yàn)閡dp沒有鏈接,所以客戶端可以同時(shí)向服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端挨個(gè)處理這些數(shù)據(jù)并返回,從而實(shí)現(xiàn)并發(fā),但這有很大的局限性,比如處理數(shù)據(jù)的時(shí)間比較長,那么后面的一個(gè)客戶端會明顯感覺到等待udp協(xié)議不會出現(xiàn)粘包
UDP是面向消息的協(xié)議,每個(gè)UDP段都是一條消息,應(yīng)用程序必須以消息為單位提取數(shù)據(jù),不能一次提取任意字節(jié)的數(shù)據(jù)唯竹,這一點(diǎn)和TCP是很不同的。
所以udp協(xié)議不用自定報(bào)頭部分,提高了傳輸效率udp協(xié)議不可靠
發(fā)送數(shù)據(jù)是將數(shù)據(jù)從應(yīng)用程序的內(nèi)存中拷貝到系統(tǒng)內(nèi)存中,通過網(wǎng)卡發(fā)送出去的
tcp協(xié)議發(fā)數(shù)據(jù)是拷貝一份數(shù)據(jù)發(fā)出去,等著對方回復(fù)一個(gè)ACK才會把系統(tǒng)內(nèi)存中的的數(shù)據(jù)刪掉,如果沒收到對方的ACK,那么過段時(shí)間還會繼續(xù)發(fā)
而UDP協(xié)議是直接將數(shù)據(jù)發(fā)出去,系統(tǒng)內(nèi)存中不做保留,他只負(fù)責(zé)發(fā),對方愛收不收,所以會出現(xiàn)丟包
UDP協(xié)議的小程序示例
udp服務(wù)端
#導(dǎo)入socket模塊
import socket
#創(chuàng)建服務(wù)器對象,socket.SOCK_DGRAM代表遵循UDP協(xié)議
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#綁定地址
server.bind(('127.0.0.1',8082))
#通信循環(huán)
while True:
#接收客戶端發(fā)來的消息以及客戶端IP與端口
data,client_addr=server.recvfrom(1024)
print(data)
#將消息轉(zhuǎn)為大寫回復(fù)給客戶端,
#兩個(gè)參數(shù)為回復(fù)信息與客戶端IP與端口
server.sendto(data.upper(),client_addr)
server.close()
udp客戶端
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg=input('>>: ').strip()
client.sendto(msg.encode('utf-8'),('127.0.0.1',8082))
data,server_addr=client.recvfrom(1024)
print(data)
2.socketserver實(shí)現(xiàn)并發(fā)
基于tcp的套接字,關(guān)鍵就是兩個(gè)循環(huán)良狈,一個(gè)鏈接循環(huán),一個(gè)通信循環(huán)
只有通信循環(huán)結(jié)束才能建立下一次連接,就好比是開了一個(gè)飯店,一個(gè)人在外面攬客,攬到客人以后自己又要去廚房做菜,還要等客人吃完結(jié)完賬才能繼續(xù)出去攬下一位客人,所以實(shí)現(xiàn)并發(fā)的思路就是 : 讓一個(gè)人專門在門口攬客,有客人后交給服務(wù)員,讓他去處理,自己繼續(xù)攬客,又來了客人后再交給另外一個(gè)服務(wù)員
server=socketserver.ThreadingTCPServer(參數(shù)一,參數(shù)二)
參數(shù)一為服務(wù)端綁定的IP以及端口
參數(shù)二為自定義的類來處理通信循環(huán)的
server.serve_forever() # 鏈接循環(huán)
- 自定義的類必須繼承
socketserver.BaseRequestHandler
- 自定義的類必須有
handle(self)
方法用來處理通信循環(huán)
基于tcp通信實(shí)現(xiàn)并發(fā)示例
服務(wù)端:
import socketserver
# 自定義類用來處理通信循環(huán)
class MyTCPhanler(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
data = self.request.recv(1024)
if len(data) == 0: break # 針對linux系統(tǒng)
print('-->收到客戶端的消息: ', data)
self.request.send(data.upper())#self.request為雙向連接對象,相當(dāng)于之前的conn
except ConnectionResetError:
break
self.request.close()
if __name__ == '__main__':
server=socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTCPhanler)
server.serve_forever() # 鏈接循環(huán)
客戶端:(客戶端不用變)
from socket import *
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8081))
# 通信循環(huán)
while True:
client.send('hello'.encode('utf-8'))
data=client.recv(1024)
print(data)
client.close()
基于UDP通信實(shí)現(xiàn)并發(fā)示例
服務(wù)端:
import socketserver
class MyUdphandler(socketserver.BaseRequestHandler):
def handle(self):
data,sock=self.request
sock.sendto(data.upper(),self.client_address)
if __name__ == '__main__':
server=socketserver.ThreadingUDPServer(('127.0.0.1',8081),MyUdphandler)
server.serve_forever()
客戶端:(還是不變)
from socket import *
client=socket(AF_INET,SOCK_DGRAM)
while True:
client.sendto(b'hello',('127.0.0.1',8081))
data,server_addr=client.recvfrom(1024)
print(data)
3.進(jìn)程理論
進(jìn)程指的是一個(gè)正在進(jìn)行/運(yùn)行的程序,進(jìn)程是用來描述程序執(zhí)行過程的虛擬概念
進(jìn)程vs程序
程序:一堆代碼
進(jìn)程:程序的執(zhí)行的過程
進(jìn)程的概念起源于操作系統(tǒng),進(jìn)程是操作系統(tǒng)最核心的概念,操作系統(tǒng)其它所有的概念都是圍繞進(jìn)程來
操作系統(tǒng)理論:
1. 操作系統(tǒng)是什么?
操作系統(tǒng)是一個(gè)協(xié)調(diào)\管理\控制計(jì)算機(jī)硬件資源與應(yīng)用軟件資源的一段控制程序
有兩大功能:
1. 將復(fù)雜的硬件操作封裝成簡單的接口給應(yīng)用程序或者用戶去使用
2. 將多個(gè)進(jìn)程對硬件的競爭變得有序
操作系統(tǒng)發(fā)展史
并發(fā): 多個(gè)任務(wù)看起來是同時(shí)運(yùn)行的
串行:一個(gè)任務(wù)完完整整地運(yùn)行完畢,才能運(yùn)行下一個(gè)任務(wù)
多道技術(shù):(復(fù)用=>共享/共用)
1. 空間上的復(fù)用:多個(gè)任務(wù)復(fù)用內(nèi)存空間
2. 時(shí)間上的復(fù)用:多個(gè)任務(wù)復(fù)用cpu的時(shí)間
1. 一個(gè)任務(wù)占用cpu時(shí)間過長會被操作系統(tǒng)強(qiáng)行剝奪走cpu的執(zhí)行權(quán)限:比起串行執(zhí)行反而會降低效率
2. 一個(gè)任務(wù)遇到io操作也會被操作系統(tǒng)強(qiáng)行剝奪走cpu的執(zhí)行權(quán)限:比起串行執(zhí)行可以提升效率