day32
今日总结:
server.listen() # 监听
client, addr = server.accept() # 三次握手
print("接到一个客人了,开始服务了!")
# 循环收发数据(例如:这是接待一个人,这个人买好多种商品的时候)
while True:
try: # 有可能recv接受数据出现问题,也有能发送数据出问题,所以try
data = client.recv(1024).decode("utf-8") # 接收数据 注意接受是客户收数据 直接进行转码
if not data: # 在这里要判断接受的数据是否为空,即客户端是否退出或者关闭程序
break # 如果为空则结束接受,断开链接
print(data)
#res = data[1:]
# print(data.decode("utf-8")) # 把接收到的数据转码
client.send(res.encode("utf-8")) # 发送数据 给客户端发数据
except ConnectionResetError as e: # 收发出问题就报这个错误 局部报错
print("客户端挂了!", e)
client.close() # 报错断开链接
break # 结束循环
client.close() # 断开链接
try:
client.connect(("127.0.0.1", 1688)) # 连接服务器
print("连接成功!")
# 循环收发数据
while True:
msg = input(":")
if msg == "q": break
if not msg: continue
client.send(msg.encode('utf-8')) # 发送数据 只能发二进制数据
data = client.recv(1024) # 接收数据 收多少字节数
print(data.decode("utf-8")) #传过来的是二进制, 把二进制进行转码
except ConnectionRefusedError as e: # 链接服务器出错,如果连接失败就走这个
print("链接服务器失败!", e)
except ConnectionResetError as e: # 如果收发出问题,此时就报这个错误, 收发失败就走这个
print("服务器挂了!", e)
client.close() # 如果连接失败,就不会走下面的代码,同样收发出现问题,也不会走下面的代码,此时都未断开链接,处于等待状态,所以要断开链接
# except Exception as e: #万能异常
# print("链接服务器失败!", e)
# print(type(e)) #<class 'ConnectionRefusedError'>
客户端思路:(基本循环模板)
1,先编写最基本完整数据结构
2,循环发收数据,首先判断发送的数据是否为空或退出
把发送的数据进行转码为二进制
把收到的二进制数据进行转码
所以在连接服务器之前使用 try,保证机器不蹦
1》,链接服务器失败 except ConnectionRefusedError as e:
2》,发收数据阻塞报错 即服务器挂了, except ConnectionResetError as e:
(except Exception as e: #万能异常)
服务端思路:(基础循环模板)
1,先编写最基本完整的服务数据结构(1:导入接口2:ip类型和规定tcp协议server=socket.socket
3:绑定本机ip和端口bind,4:监听listen5:建立连接accept,三次握手6:接受数据revc
7:发送数据send 8:断开链接 client.close() ,注意,收发数据都是客户端即client.revc和client.send,并且注 意进制转码。)
2,循环收发数据,首先判断接收的数据是否为空
把接受到的二进制数据进行转码,你才能看懂
把发送的数据进行二进制转码
3,收发数据时无法预知哪里出现问题和阻塞
所以在收发数据之前使用 try,即三次保证机器不蹦
4,循环接受数据,例:即接完一个客户后继续接下一个客户
在三次握手之前
5,报错信息:except ConnectionResetError as e: # 收发出问题就报这个错误 局部报错
print("客户端挂了!", e)
break # 结束循环 client.close() # 断开链接
server.bind(("127.0.0.1", 1688))
server.listen(5)
# 5就是最大半连接数 本质就是一个数组,未完成的就会被加入到数组中
# 每一次执行accept 就会挑出一个来完成三次握手,如果达到最大限制,额外的就会被直接拒绝
# 我们可以调整内核参数来修改 最大等待时长,如果超时,客户还是没有回复第三次握手信息,就直接删除
粘包问题:
import socket
import subprocess
server = socket.socket()
server.bind(("127.0.0.1",1589)) #必须为元组
server.listen()
while True:
client,addr = server.accept()
print("客户端连接成功,开始")
while True:
try:
data = client.recv(1024).decode("utf-8") # 接收数据
if not data:
break
print(data)
#第一个参数填的是指令 shell=True,第三个是管道,输出管道和错误管道
# 要建管道,把数据丢进管道,不然的话数据就会出现在屏幕终端
p = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# 读数据 不要先读err信息,它会卡住 原因不详 linux不会有问题,例如tasklist列出任务列表,netstat-ano 啥的都不行
data = p.stdout.read()
err_data = p.stderr.read()
# 返回的结果就是二进制,所以不需要进行转码
client.send(data + err_data ) # 发送数据
# client.close()
except ConnectionResetError as e:
print("客户端挂了!",e)
client.close()
break
client.close()