python-sockertserver并发编程思想

团子的守护 2021-11-25 13:29:27
编程 Python 并发 python-sockertserver sockertserver

听了林海峰老师讲的sockertserver的总结

一、首先在socketserver模块中分两大类:

server类(解决链接问题)和request类(解决通信问题)

1、server类

 2、request类:

 二、我将先为大家讲解基于TCP的sockertserver的基本使用

服务端代码:

import socketserver
class MyRequestHandle(socketserver.BaseRequestHandler):
def handle(self):
print(self.request) # 如果是tcp协议,self.request=>conn
print(self.client_address)
while True:
try:
msg=self.request.recv(1024)
if len(msg)==0:break
self.request.send(msg.upper())
except Exception:
break
self.request.close()
'''
s.serve_forever()=>等同于以下代码
while True:
conn,client_addr=server.accept()
启动一个线程(conn,client_addr)
'''
# 服务端应该做两件事
# 1、第一件事:循环的从半链接池中取出链接请求与其建立双向链接,拿到链接对象
s = socketserver.ThreadingTCPServer(('127.0.0.1', 8888), MyRequestHandle)
s.serve_forever()
# 2、拿到链接对象,与其进行通信循环==>handle

客户端1代码:

from socket import *
import struct
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8888))
while True:
msg=input('请输入命令>>>>').strip()
if len(msg)==0:
continue
client.send((msg.encode('utf-8')))
recv_data=client.recv(1024)
print(recv_data.decode('utf-8'))

客户端2代码:

from socket import *
import struct
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8888))
while True:
msg=input('请输入命令>>>>').strip()
if len(msg)==0:
continue
client.send((msg.encode('utf-8')))
recv_data=client.recv(1024)
print(recv_data.decode('utf-8'))

运行结果:

# 服务端结果:
<socket.socket fd=812, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8888), raddr=('127.0.0.1', 63110)>
('127.0.0.1', 63110)
<socket.socket fd=692, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8888), raddr=('127.0.0.1', 63115)>
('127.0.0.1', 63115)
# 客户端1结果:
请输入命令>>>>asasa
ASASA
请输入命令>>>>ds
DS
请输入命令>>>>
# 客户端2结果:
请输入命令>>>>asas
ASAS
请输入命令>>>>

可以看出客户端1和客户端2是同时进行操作的,服务端同时接收到了两个消息

三、下面来为大家介绍基于UDP的sockertserver的并发思想

服务端代码:

import socketserver
class MyRequestHandle(socketserver.BaseRequestHandler):
def handle(self):
client_data=self.request[0]
server=self.request[1]
client_addr=self.client_address
print('客户端发来的数据%s'%client_data)
server.sendto(client_data.upper(),client_addr)
s=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyRequestHandle)
s.serve_forever()
# 相当于只负责循环的收
'''
s.serve_forever()=>等同于以下代码
while True:
data,client_addr=server.accept()
启动一个线程处理后续的事情(data,client_addr)
'''

客户端1代码:

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)# 数据报协议=》udp协议
while True:
msg=input('>>>>')
client.sendto(msg.encode('utf-8'),("127.0.0.1",8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'),server_addr)
client.close()

客户端2代码:

import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)# 数据报协议=》udp协议
while True:
msg=input('>>>>')
client.sendto(msg.encode('utf-8'),("127.0.0.1",8080))
data,server_addr=client.recvfrom(1024)
print(data.decode('utf-8'),server_addr)
client.close()

运行结果为:

# 服务端代码:
客户端发来的数据b'asa'
客户端发来的数据b'asasa'
客户端发来的数据b'asasasa'
# 客户端1代码:
>>>>asa
ASA ('127.0.0.1', 8080)
>>>>asasa
ASASA ('127.0.0.1', 8080)
>>>>
#客户端2代码:
>>>>asasasa
ASASASA ('127.0.0.1', 8080)
>>>>

四、用sockertserver基于TCP实现多客户远程执行命令

服务端:

import socketserver
import subprocess
import struct
import json
class MyRequestHandle(socketserver.BaseRequestHandler):
def handle(self):
print(self.request) # 如果是tcp协议,self.request=>conn
# print(self.client_address)
while True:
try:
cmd = self.request.recv(1024)
if len(cmd) == 0:
break
obj = subprocess.Popen(cmd.decode('utf-8'), # pycharm默认格式为utf-8
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_res = obj.stdout.read()
stderr_res = obj.stderr.read()
total_size = len(stdout_res) + len(stderr_res)
header_dic = {
'total_size': total_size,
'client_address':self.client_address
}
print('客户端:%s 命令长度为:%d'%(header_dic['client_address'],header_dic['total_size']))
json_str = json.dumps(header_dic)
json_str_bytes = json_str.encode('utf-8')
# 2、先发头的长度
x = struct.pack('i', len(json_str_bytes)) # 将整形转换为bytes类型
self.request.send(x)
# 3、发头信息
self.request.send(json_str_bytes)
# 4再发真实的数据
self.request.send(stdout_res + stderr_res)
except Exception:
break
self.request.close()
'''
s.serve_forever()=>等同于以下代码
while True:
conn,client_addr=server.accept()
启动一个线程(conn,client_addr)
'''
# 服务端应该做两件事
# 1、第一件事:循环的从半链接池中取出链接请求与其建立双向链接,拿到链接对象
s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyRequestHandle)
s.serve_forever()
# 2、拿到链接对象,与其进行通信循环==>handle

客户端1

from socket import *
import struct
import json
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
msg=input('请输入命令>>>>').strip()
if len(msg)==0:
continue
client.send((msg.encode('utf-8')))
# 解决粘包问题:
# 一、先收固定长度的头:解析出数据的描述信息,包括拿数据的总大小total_size
# 1、先接收4个字节,从中提取接下来要收的头的长度
x = client.recv(4)
header = struct.unpack('i', x)[0]
# 2、接收头并解析
json_str_bytes = client.recv(header)
json_str = json_str_bytes.decode('utf-8')
header_dic =json.loads(json_str)
total_size = header_dic['total_size']
# 3、接收真实数据
recv_size=0
while recv_size<total_size:
recv_data=client.recv(1024)# 当收到的数据超过1024时,剩下的数据会继续在客户端的缓存中,新的数据也会在客户端的缓存中,等剩下的数据接收完了再接收新的数据
recv_size+=len(recv_data)
print(recv_data.decode('gbk'),end='')# windows默认是gbk格式,解码应为gbk格式
else:
print()

客户端2

from socket import *
import struct
import json
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
msg=input('请输入命令>>>>').strip()
if len(msg)==0:
continue
client.send((msg.encode('utf-8')))
# 解决粘包问题:
# 一、先收固定长度的头:解析出数据的描述信息,包括拿数据的总大小total_size
# 1、先接收4个字节,从中提取接下来要收的头的长度
x = client.recv(4)
header = struct.unpack('i', x)[0]
# 2、接收头并解析
json_str_bytes = client.recv(header)
json_str = json_str_bytes.decode('utf-8')
header_dic =json.loads(json_str)
total_size = header_dic['total_size']
# 3、接收真实数据
recv_size=0
while recv_size<total_size:
recv_data=client.recv(1024)# 当收到的数据超过1024时,剩下的数据会继续在客户端的缓存中,新的数据也会在客户端的缓存中,等剩下的数据接收完了再接收新的数据
recv_size+=len(recv_data)
print(recv_data.decode('gbk'),end='')# windows默认是gbk格式,解码应为gbk格式
else:
print()

运行结果:

# 服务端结果:
<socket.socket fd=380, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 64118)>
客户端:('127.0.0.1', 64118) 命令长度为:20828
<socket.socket fd=752, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 64121)>
客户端:('127.0.0.1', 64121) 命令长度为:583
# 客户端1结果:
请输入命令>>>>tasklist
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 8 K
System 4 Services 0 84 K
Registry 124 Services 0 63,832 K
smss.exe 520 Services 0 1,036 K
csrss.exe 736 Services 0 5,152 K
wininit.exe 824 Services 0 5,752 K
csrss.exe 836 Console 1 6,856 K
services.exe 904 Services 0 9,748 K
lsass.exe 924 Services 0 24,384 K
svchost.exe 528 Services 0 33,208 K
fontdrvhost.exe 576 Services 0 2,452 K
svchost.exe 936 Services 0 16,768 K
svchost.exe 1044 Services 0 10,024 K
winlogon.exe 1212 Console 1 12,444 K
fontdrvhost.exe 1276 Console 1 10,464 K
dwm.exe 1356 Console 1 92,164 K
svchost.exe 1416 Services 0 10,700 K
svchost.exe 1516 Services 0 9,760 K
svchost.exe 1528 Services
。。。。。。。。。。。。。。。。。。。。。。。
conhost.exe 3528 Console 1 11,800 K
cmd.exe 8540 Console 1 5,092 K
tasklist.exe 15936 Console 1 9,652 K
请输入命令>>>>
# 客户端2
请输入命令>>>>dir
驱动器 D 中的卷是 所有文件软件丢到这里来
卷的序列号是 C0F9-5D0A
D:\新建文件夹\pythonProject1\shujialianxi\基于socketserver模板实现并发\基于TCP 的目录
2021/11/25 00:59 <DIR> .
2021/11/25 00:59 <DIR> ..
2021/11/25 00:01 <DIR> sockertserver基本使用
2021/11/24 11:46 0 __init__.py
2021/11/24 11:44 328 客户端.py
2021/11/24 11:44 328 客户端2.py
2021/11/25 00:59 2,171 服务端.py
4 个文件 2,827 字节
3 个目录 37,787,205,632 可用字节
请输入命令>>>>

版权声明
本文为[团子的守护]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_51734025/article/details/121528018

  1. Utilisez Python pour proposer l'année de la colonne de date dans les deux CSV, faire une nouvelle colonne, puis combiner les deux tableaux CSV en un seul tableau avec la colonne de date et le numéro d'identification.
  2. 关于#python#的问题,请各位专家解答!
  3. ***
  4. ***
  5. 關於#python#的問題,請各比特專家解答!
  6. S'il vous plaît répondre aux questions de Python!
  7. About the import of Python class
  8. Magic Python property decorator: 1 line of code makes Python methods become properties in seconds
  9. Python 音频调整音量(附代码) | Python工具
  10. Python programming ideas [series of articles]
  11. Python crawler programming idea (67): modify nodes using pyquery
  12. Python crawler programming idea (66): using pyquery to obtain node information
  13. Python crawler programming idea (65): find nodes using pyquery
  14. Python crawler programming idea (64): using CSS selectors in pyquery
  15. Python crawler programming idea (63): basic knowledge of pyquery
  16. Python crawler programming idea (62): project practice: capturing cool dog online red song list
  17. Python crawler programming idea (61): project practice: capturing rental information
  18. Python crawler programming idea (60): get CSS selector code through browser
  19. Python爬虫编程思想(85):在Python中使用非关系型数据库
  20. Volume de réglage audio Python (avec Code) | outils Python
  21. Python crawler programming idea (59): get attribute value and text with beautiful soup CSS selector
  22. Python crawler programming idea (58): nested selection nodes with beautiful soup CSS selectors
  23. Python crawler programming idea (57): basic usage of CSS selector in beautiful soup
  24. Python crawler programming idea (56): find method of beautiful soup method selector
  25. Python crawler programming idea (55): find of beautiful soup method selector_ All method
  26. Python crawler programming idea (54): use beautiful soup to select sibling nodes
  27. Python crawler programming idea (53): use beautiful soup to select the parent node
  28. Django3.0 solves the problem of error reporting in reverse parsing
  29. Precautions for Python crawler
  30. Python 3 crawler series (1) -- climbing blind date websites
  31. Python到底是什么?为什么要学Python?
  32. #yyds干货盘点#Pandas数据清洗实用指南
  33. Python打包exe文件无法运行
  34. Two common ways to save files in Python
  35. #yyds幹貨盤點#Pandas數據清洗實用指南
  36. Yyds Dry Inventory pandas Data Cleaning Practical Guide
  37. PYTHON用LSTM长短期记忆神经网络的参数优化方法预测时间序列洗发水销售数据
  38. Python集成学习:自己编写构建AdaBoost分类模型可视化决策边界及sklearn包调用比较
  39. Python 3 makes a search software
  40. Python 3 simulated microblog login
  41. Using Python 3 to make practical software for drawing modification
  42. About HTML (acceptable to Python)
  43. Python集成學習:自己編寫構建AdaBoost分類模型可視化决策邊界及sklearn包調用比較
  44. PYTHON用LSTM長短期記憶神經網絡的參數優化方法預測時間序列洗發水銷售數據
  45. Python Integrated Learning: Writing and Constructing adaboost Classification Model Visualized decision Boundary and sklearn package Calling Comparison
  46. Python prédit les données de vente de shampooing de séries chronologiques en utilisant la méthode d'optimisation des paramètres du réseau neuronal de mémoire à court et à long terme lstm
  47. [zero basics of Python to introduction] a prerequisite for Python preparatory knowledge -- basic coding specification of Python
  48. OpenCV对比度亮度变换竟能用来去水印(附Python/C++源码)
  49. [zero basics of Python to getting started] a prerequisite for Python preparatory knowledge -- installing the visualization tool pycharm
  50. The test modifies main.py in micro python
  51. Microphoton experimental circuit board based on mm32f3273 - does not work normally
  52. Run micropathon on mm32f3273 to test performance
  53. Design mm32f3277 micro Python experimental board with SD card
  54. Mm32f3277 corresponding interface files during microphoton migration
  55. Mm32f3277 microphoton experimental board design and software testing
  56. Making and testing mm32f3277 microphoton minimum circuit board
  57. Download mm32-link program automatically with Python simulated mouse
  58. A curriculum of "artificial intelligence Python machine learning and deep learning"
  59. Test the basic functions of mm32 microphoton test circuit board
  60. Test the basic functions of the mm32f3277 micro Python development board flying one by one