1.网络通信
1.1 UDP通信
UDP 英文全拼 (User Datagram Protocol) 简称用户数据报协议, 它是无连接的、不可靠的网络传输协议。
优点 : 不需要连接 资源开销小 传输速度快 每个数据包64K 缺点 : 数据传输不安全容易丢包 没有流量控制.会导致缓冲区的数据堆积。
函数 socket.socket 创建一个 socket,该函数带有两个参数: Address Family:IP地址类型; AF_INET表示ipv4类型、AF_INET6表示ipv6类型; Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
// 发送接收数据-客户端
import socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dest_addr = ('127.0.0.1', 8080)
send_data = input("请输入要发送的数据:")
udp_socket.sendto(send_data.encode('utf-8'), dest_addr)
recv_data = udp_socket.recvfrom(1024)
print(recv_data[0].decode('gbk'))
print(recv_data[1])
udp_socket.close()
// 发送接收数据 -服务器
from socket import *
udp_socket = socket(AF_INET, SOCK_DGRAM)
local_addr = ('', 7788)
udp_socket.bind(local_addr)
recv_data = udp_socket.recvfrom(1024)
print(recv_data[0].decode('gbk'))
1.2 TCP通信
13.2 TCP
TCP:英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议, TCP通信需要经过创建连接、数据传送、终止连接三个步骤。
优点: 可靠,稳定 适合传输大量数据 缺点: 传输速度慢 占用系统资源高
// TCP客户端
import socket
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip = input("请输入服务器ip:")
server_port = int(input("请输入服务器port:"))
tcp_client_socket.connect((server_ip, server_port))
send_data = "".join([x for x in range(10)])
tcp_client_socket.send(send_data.encode("gbk"))
recvData = tcp_client_socket.recv(1024)
print('接收到的数据为:', recvData.decode('gbk'))
tcp_client_socket.close()
//TCP服务器
import socket
tcp_server_socket = socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('127.0.0.1', 8080)
tcp_server_socket.bind(address)
tcp_server_socket.listen(128)
client_socket, clientAddr = tcp_server_socket.accept()
recv_data = client_socket.recv(1024)
print('接收到的数据为:', recv_data.decode('gbk'))
client_socket.send("thank you !".encode('gbk'))
client_socket.close()
2. 文件下载器
2.1 服务端
import socket
import os
def main():
tcp_serve_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_serve_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_serve_socket.bind(("", 9090))
tcp_serve_socket.listen(128)
while True:
service_client_socket, ip_port = tcp_serve_socket.accept()
file_name_data = service_client_socket.recv(1024)
file_name = file_name_data.decode("gbk")
print(file_name, ip_port)
if os.path.exists(file_name):
with open(file_name, "rb") as file:
while True:
file_data = file.read(1024)
if file_data:
service_client_socket.send(file_data)
else:
break
else:
print("文件不存在")
service_client_socket.close()
tcp_serve_socket.close()
2.2 客户端
import socket
def main():
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_client_socket.connect(("192.168.107.160", 9090))
file_name = input("请输入您要下载的文件名:")
file_name_data = file_name.encode("gbk")
tcp_client_socket.send(file_name_data)
with open("/home/python/Desktop/" + file_name, "wb") as file:
while True:
file_data = tcp_client_socket.recv(1024)
if file_data:
file.write(file_data)
else:
break
tcp_client_socket.close()
3.多线程
3.1 线程
线程的特点:线程之间执行是无序的 主线程会等待所有的子线程结束后才结束(线程主要处理cpu密集型)。
import threading
import time
def sing(num):
for i in range(num):
print("正在唱歌...%d" % i)
time.sleep(1)
def dance(num):
for i in range(num):
print("正在跳舞...%d" % i)
time.sleep(1)
if __name__ == '__main__':
sing_thread = threading.Thread(target=sing, args=(3, ))
dance_thread = threading.Thread(target=dance, kwargs={"num": 3},daemon=True)
sing_thread.start()
dance_thread.start()
使用互斥锁
mutex = threading.Lock()
mutex.acquire()
mutex.release()
import threading
g_num = 0
lock = threading.Lock()
def sum_num1():
lock.acquire()
for i in range(1000000):
global g_num
g_num += 1
print("sum1:", g_num)
lock.release()
def sum_num2():
lock.acquire()
for i in range(1000000):
global g_num
g_num += 1
print("sum2:", g_num)
lock.release()
if __name__ == '__main__':
first_thread = threading.Thread(target=sum_num1)
second_thread = threading.Thread(target=sum_num2)
first_thread.start()
second_thread.start()
3.2 进程
一个程序至少有一个进程,一个进程至少有一个线程,多进程可以完成多任务(进程主要处理 IO 密集型)
import multiprocessing
def show_info(name, age):
print(name, age)
if __name__ == '__main__':
sub_process = multiprocessing.Process(target=show_info, name="myprocess",
args=("zhangsan", 18))
sub_process.start()
time.sleep(1)
print("主进程执行完成了啦")
sub_process.terminate()
3.3 队列
Queue的使用可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息列队程序,首先用一个小实例来演示一下Queue的工作原理
import multiprocessing
import time
if __name__ == '__main__':
queue = multiprocessing.Queue(3)
queue.put(1)
queue.put("hello")
queue.put([3,5])
if queue.qsize() == 0:
print("队列为空")
else:
print("队列不为空")
size = queue.qsize()
print(size)
value = queue.get()
print(value)
3.4 进程池
同步进程池 进程池同步执行任务表示进程池中的进程在执行任务的时候一个执行完成另外一个才能执行,如果没有执行完会等待上一个进程执行。
import multiprocessing
import time
def work():
print("复制中...", multiprocessing.current_process().pid)
time.sleep(0.5)
if __name__ == '__main__':
pool = multiprocessing.Pool(3)
for i in range(5):
pool.apply(work)
异步进程池 进程池异步执行任务表示进程池中的进程同时执行任务,进程之间不会等待。
import multiprocessing
import time
def work():
print("复制中...", multiprocessing.current_process().pid)
time.sleep(0.5)
if __name__ == '__main__':
pool = multiprocessing.Pool(3)
for i in range(5):
pool.apply_async(work)
pool.close()
pool.join()
3.5 协程
greenlet实现协程
pip3 install greenlet
import time
import greenlet
def work1():
for i in range(5):
print("work1...")
time.sleep(0.2)
g2.switch()
def work2():
for i in range(5):
print("work2...")
time.sleep(0.2)
g1.switch()
```python
在这里插入代码片
if name == ‘main’: # 创建协程指定对应的任务 g1 = greenlet.greenlet(work1) g2 = greenlet.greenlet(work2)
# 切换到第一个协程执行对应的任务
g1.switch()
Gevent实现协程
```python
import gevent
import time
from gevent import monkey
# 打补丁,让gevent框架识别耗时操作,比如:time.sleep,网络请求延时
monkey.patch_all()
# 任务1
def work1(num):
for i in range(num):
print("work1....")
time.sleep(0.2)
# gevent.sleep(0.2)
# 任务1
def work2(num):
for i in range(num):
print("work2....")
time.sleep(0.2)
# gevent.sleep(0.2)
if __name__ == '__main__':
# 创建协程指定对应的任务
g1 = gevent.spawn(work1, 3)
g2 = gevent.spawn(work2, 3)
# 主线程等待协程执行完成以后程序再退出
g1.join()
g2.join()
|