socketserver 模块:
首先,要自定义类继承socketserver.BaseRequestHandler
这个类中的属性:
self.request : 连接对象
self.client_address : 客户端地址
创建好类之后,
server = socketserver.ThreadingTCPServer(('127.0.0.1',8083),Myserver)
产生server这个服务端对象,第一个参数服务端地址,第二个,关联这个类,得到连接对象,要用这个类处理。
所以,不用bind地址,
最后,
server.serve_forever()
不断地从半连接池中取出连接对象,交给一个线程进行处理。
TCP协议:
服务端
from socket import *
import subprocess
import struct
import socketserver
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
# self.client_address
# self.request
# 第二件事:拿到链接对象,与其进行通信循环
while True:
try:
data = self.request.recv(1024) # 最大接收的数据量为1024Bytes,收到的是bytes类型
if len(data) == 0:
# 在unix系统洗,一旦data收到的是空
# 意味着是一种异常的行为:客户度非法断开了链接
break
result = subprocess.Popen(data.decode('utf-8'), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out = result.stdout.read()
err = result.stderr.read()
self.request.send(struct.pack('i', len(out) + len(err)))
self.request.send(out)
self.request.send(err)
print("客户端发来的消息:", data.decode('utf-8'))
except Exception:
# 针对windows系统
break
# 6、关闭电话连接conn(必选的回收资源的操作)
self.request.close()
# 7、关机(可选操作) 要实现不断地从半连接池中取出连接请求,服务器不能关闭
# phone.close()
server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Myserver)
server.serve_forever()
# phone=socket(AF_INET,SOCK_STREAM) # 流式协议=》tcp协议
# phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
# phone.bind(('127.0.0.1',8083)) # 0-65535, 1024以前的都被系统保留使用
# phone.listen(5) # 5指的是半连接池的大小
# 服务端应该做两件事
# 第一件事:循环地从板连接池中取出链接请求与其建立双向链接,拿到链接对象
客户端:
import socket
import struct
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp协议
phone.connect(('127.0.0.1',8080))
while True:
msg=input("命令>>>: ").strip() #msg=''
if len(msg) == 0:continue
phone.send(msg.encode('utf-8'))
top = phone.recv(4)
top_len = struct.unpack('i',top)
size = 0
while size < top[0]:
data=phone.recv(1024)
print(data.decode('gbk'),end='')
size += len(data)
#4、关闭连接(必选的回收资源的操作)
phone.close()
UDP协议:
服务端:
import socketserver
class MyRequestHanlde(socketserver.BaseRequestHandler):
def handle(self):
client_data=self.request[0]
server=self.request[1]
client_address=self.client_address
print('客户端发来的数据%s' %client_data)
server.sendto(client_data.upper(),client_address)
s=socketserver.ThreadingUDPServer(("127.0.0.1",8888),MyRequestHanlde)
s.serve_forever()
# 相当于:只负责循环地收
# while True:
# data,client_addr=server.recvfrom(1024)
# 启动一个线程处理后续的事情(data,client_addr)
客户端:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 流式协议=》tcp协议
while True:
msg=input('>>>: ').strip()
client.sendto(msg.encode('utf-8'),('115.29.65.16',8888))
res=client.recvfrom(1024)
print(res)
client.close()