第三十天
回顾
tcp协议的多人多次通信
- 和一个人通信说多句话
- 和一个人聊完在和其他人聊
- socket() tcp协议 的server
- bind 绑定一个ip 和端口
- listen 剪影 代表socket 服务的开启
- accept 等 到有客户端来访问和客户端建立连接
- send 直接通过连接发送消息 不需要写地址
- recv 只接受消息
- connect 客户端 tcp 协议 的方法 和server 端建立连接
- close 关闭服务\链接
udp协议
socket(type=socket.SOCK_DGRAM)
sendto 需要写一个对方的地址
recvfrom 接收消息和地址
close 关闭服务\链接
没一句话什么意思?执行到哪里程序会阻塞? 为什么阻塞? 什么时候结束阻塞?
-
input() 等待 指导用户输入enter键
-
accept() 阻塞 有客户端和我建立连接之后
-
recv() 阻塞,直到收到对方的消息之后
-
recvfrom 阻塞 直到收到对方的消息之后
-
connect 阻塞 直到server 端结束了一个对client的服务 开始和当前的client建立连接的时候
粘包现象
tcp是流式传输,数据和数据之间没有边界
解决粘包现象 :
先发送4字节的数据长度 先接受4字节 知道数据长度
再按照长度发送数据 在按照长度接收数据
今日
tcp协议的自定义协议解决年报问题
验证客户端的合法性
并发的TCP协议 server端 socketserver
udp 转发
服务端
import socket
friend_lst={'alex':'32','太白':'33'}
sk=socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',9001))
dic={}
while 1:
msg,addr=sk.recvfrom(1500)
msg=msg.decode('utf-8')
name,message=msg.split('|')
# print(addr)
if name not in dic:
dic[name]=addr
# print(dic)
msg='\033[1;%sm %s:%s\033[0m'%(friend_lst.get(name,'30'),name,message)
# print(msg)
# content=input('>>>')
if len(dic)==2:
if name =='alex':
sk.sendto(msg.encode('utf-8'),dic['太白'])
else:
sk.sendto(msg.encode('utf-8'), dic['alex'])
# if content.upper()=='Q':break
客户端1
import socket
name='太白'
sk=socket.socket(type=socket.SOCK_DGRAM)
while 1:
content=input('>>>')
if content.upper()=='Q':break
content ="%s|%s" %(name,content)
sk.sendto(content.encode('utf-8'),('127.0.0.1',9001))
msg=sk.recv(1024).decode('utf-8')
# if msg.upper() == 'Q': break
print(msg)
客户端2
import socket
name='alex'
sk=socket.socket(type=socket.SOCK_DGRAM)
while 1:
content=input('>>>')
if content.upper()=='Q':break
content ="%s|%s" %(name,content)
sk.sendto(content.encode('utf-8'),('127.0.0.1',9001))
msg=sk.recv(1024).decode('utf-8')
# if msg.upper() == 'Q': break
print(msg)
#
# msg=sk.recv(1024)
# print(msg)
# sk.send(b'bye')
#
# sk.close()
基于tcp协议 收文件第一种 发送小文件 不考虑粘包
服务端
import socket
import json
sk=socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,_=sk.accept()
msg=conn.recv(1024).decode('utf-8')
msg=json.loads(msg) #json语句 转换成普通
with open (msg['filename'],'wb') as f:
content=conn.recv(msg['filesize'])
print(('->',len(content)))
f.write(content)
conn.close()
sk.close()
客户端 --发送端
import os
import socket
import json
sk=socket.socket()
sk.connect(('127.0.0.1',9001))
abc_path=r'C:\Users\Administrator\Desktop\小丁变优秀的代码\day31\asdas.py'
filename=os.path.basename(abc_path)
filesize=os.path.getsize(abc_path)
dic={'filename':filename,'filesize':filesize}
str_dic=json.dumps(dic) # 转换成 json 语句
sk.send(str_dic.encode('utf-8'))
with open(abc_path,mode='rb') as f:
content=f.read()
sk.send(content)
sk.close()
基于tcp协议 收文件第一种 发送大文件 要考虑粘包
#接收端
import socket
import json
import struct
sk=socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
conn,_=sk.accept()
msg_len=conn.recv(4)
dic_len=struct.unpack('i',msg_len)[0] # 收到的解包 是一个元祖 第0 个 才是咱们想要的长度
msg=conn.recv(dic_len).decode('utf-8')
msg=json.loads(msg) #json语句 转换成普通
with open (msg['filename'],'wb') as f:
while msg['filesize']>0:
content=conn.recv(1024)
msg['filesize']-=len(content) #每次减去实际收到的字节数 有效解决粘包问题
f.write(content)
conn.close()
sk.close()
发送端
import os
import socket
import json
import struct
sk=socket.socket()
sk.connect(('127.0.0.1',9001))
abc_path=r'C:\Users\Administrator\Desktop\小丁变优秀的代码\day31\asdas.py'
filename=os.path.basename(abc_path)
filesize=os.path.getsize(abc_path)
dic={'filename':filename,'filesize':filesize}
str_dic=json.dumps(dic) # 转换成 json 语句
b_dic=str_dic.encode('utf-8') #先转成 'utf-8' 格式 再进行 struct
mlen=struct.pack('i',len(b_dic))#struct 包 转换成4 字节
sk.send(mlen) #4个字节 表示字典的转成 字节之后的长度
sk.send(b_dic) # 具体的字典的数据
with open(abc_path,mode='rb') as f:
while filesize>0:
content=f.read(1024)
filesize-=1024
sk.send(content)
sk.close()
socketserver--处理并发客户端请求 并发
### socket 底层模块 封装度低 效率不固定
### socketserver基于socket完成的 封装度高
tcp协议的server 端处理并发的客户端请求
网盘:文件的 上传与下载
.
#持续发消息, 当一个连接断了以后, 下一个连接再连上的时候 直接继续发消息
# 其实想要实现的是一个并发网络编程
#用 socket 实现的 是一个基础的模型
#下面开始 使用socketserver 模块 实现
#服务端
import socket
import time
sk= socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()
while 1:
conn, _ = sk.accept()
while 1:
try:
content=conn.recv(1024).decode('utf-8')
conn.send(content.upper().encode('utf-8'))
time.sleep(0.5)
except ConnectionResetError:
break
#客户端
import socket
sk= socket.socket()
sk.connect(('127.0.0.1',9001))
while 1:
sk.send(b'hello')
content= sk.recv(1024).decode('utf-8')
print(content)
并发 socketserver
# 每一个客户端连上之后 都进入了 handle函数里面了
# 每一个客户端都有一个 handle 互不干扰
$$$$$$$$$$$$$$$$$$$背会$$$$$$$$$$$$$$$$$$$
import time
import socketserver #******************
class Myserver(socketserver.BaseRequestHandler): #BaseRequestHandler #******************
def handle(self): #******************
# print(self.request)
# < socket.socket
# fd = 756, family = AddressFamily.AF_INET, type = SocketKind.SOCK_STREAM, proto = 0, laddr = ('127.0.0.1',
# 9001), raddr = (
#
#
conn = self.request
while 1:
try:
content = conn.recv(1024).decode('utf-8')
conn.send(content.upper().encode('utf-8'))
time.sleep(0.5)
except ConnectionResetError:
break
server=socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver) #ThreadingTCPServer #******************
server.serve_forever() #******************
import time
import socketserver
class Myserver(socketserver.BaseRequestHandler):
def Handel(self):
conn=self.request
server=socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)
server.serve_forever()
# self.requset 打印
# laddr=('127.0.0.1', 9001), raddr=('127.0.0.1', 13958)>
# 只有自己的地址的 是sk
# 有自己的 也有对方的地址 是 conn
客户端还是和原来一样
对代码有疑问欢迎交流
一个python爱好者 :
微信:at8685b

浙公网安备 33010602011771号