应用层协议
http ftp smtp
import socket
sk=socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen()
conn,addr=sk.accept()
ret=conn.recv(2) #缓存机制 接收端的缓存机制
ret2=conn.recv(10)
print(ret)
print(ret2)
conn.close()
sk.close()
#黏包的原因是 因为不知道客户端发送的数据长度
####
import socket
sk=socket.socket()
sk.connect(('127.0.0.1',8090))
sk.send(b'hello,tangdou')
sk.close()
##连续小数据包 会合并
#多个send 小的数据 连在一起 会发生黏包现象,是tcp协议 内部算法所致 非常短的时间
#先发先走
队列
import queue
ql=queue.Queue()
ql.put(1)
print(ql.qsize())
ql.get() #pop
黏包现象
import socket
sk=socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen()
conn,addr=sk.accept()
ret=conn.recv(2) #缓存机制 接收端的缓存机制
ret2=conn.recv(10)
print(ret)
print(ret2)
conn.close()
sk.close()
#黏包的原因是 因为不知道客户端发送的数据长度
###客户端
import socket
sk=socket.socket()
sk.connect(('127.0.0.1',8090))
sk.send(b'hello,tangdou')
sk.close()
#解决准则
import socket
sk=socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,add=sk.accept()
while 1:
cmd=input(">>>")
if cmd=='q':
conn.send(b'q')
break
conn.send(cmd.encode('gbk'))
num=conn.recv(1024).decode('gbk')
conn.send(b'ok')
res=conn.recv(int(num)).decode('gbk')
print(res)
conn.close()
sk.close()
#client
import socket
import subprocess
sk=socket.socket()
sk.connect(('127.0.0.1',8080))
while 1:
cmd=sk.recv(1024).decode('gbk')
if cmd==b'q':
break
res=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
std_out=res.stdout.read() #由于数据只能存储一次 队列操作
sk.send(str(len(std_out)).encode('utf-8'))
sk.recv(1024) # ok
sk.send(std_out)
sk.close()
#确定接收多大的数据
#别人发多少 我给发多少 send 超过一定范围报错
#要在文件配置一个配置项 就是每一次recv的大小 不超过 4096
#多用文件传输过程中
###大文件的传输 一定是按照字节读 每一次读固定 的字节
####传输过程中 一边读一边传,接收端 一边收 一边写
内部函数strut
可以吧数字转化为固定的bytes
import socket
import struct
sk=socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,add=sk.accept()
while 1:
cmd=input(">>>")
if cmd=='q':
conn.send(b'q')
break
conn.send(cmd.encode('gbk'))
num=conn.recv(4)
num=struct.unpack('i',num)[0]
res=conn.recv(int(num)).decode('gbk')
print(res)
conn.close()
sk.close()
#
import socket
import subprocess
import struct
sk=socket.socket()
sk.connect(('127.0.0.1',8080))
while 1:
cmd=sk.recv(1024).decode('gbk')
if cmd==b'q':
break
res=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
std_out=res.stdout.read() #由于数据只能存储一次 队列操作
len_num=len(std_out)
num_by= struct.pack('i',len_num)
sk.send(num_by)
sk.send(std_out)
sk.close()
#确定接收多大的数据
#别人发多少 我给发多少 send 超过一定范围报错
#要在文件配置一个配置项 就是每一次recv的大小 不超过 4096
#多用文件传输过程中
###大文件的传输 一定是按照字节读 每一次读固定 的字节
####传输过程中 一边读一边传,接收端 一边收 一边写
#我们在网络上传输的所有数据 都叫数据包
#数据包里的所有数据 都叫报文
报文 都有 数据 IP地址 mac 地址 端口号
协议里面都有包头 接收多少个字节
自己定制报文
比如说 复杂的应用上就会用到
传输文件
传输文件 传输大小 文件的类型 存储路径
#其实 在网络传输中过程 处处有协议
#协议就是一堆报文和报头 ---字节
#解析过程不需要担心
#协议本质上是一种约定
#我们也可以自定义协议
ftp的搭建
#实现大文件的上传或者下载
#配置文件 ip 地址 端口号
import socket #jieshou
import struct
import json
sk=socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen()
buffer=1024
conn,addr=sk.accept()
#接受端
head_len=conn.recv(4)
head_len=struct.unpack('i',head_len)[0]
json_head=conn.recv(head_len).decode('utf-8')
head=json.loads(json_head)
filesize=head['filesize']
#file_path='D:\\'
with open(head['filename'],'wb') as f:
while filesize:
if filesize>=buffer:
content=conn.recv(buffer)
f.write(content)
filesize-=buffer
else:
content = conn.recv(filesize)
f.write(content)
break
print("——————服务端——————")
conn.close()
sk.close()
客户端
import socket
import os
import json
import struct
sk=socket.socket()
sk.connect(('127.0.0.1',8090))
buffer=1024
#发送文件
#报头
head={'filepath':r'D:\BaiduNetdiskDownload\2015考研日语(203)复试指导',
'filename':r'1 面试礼仪及用语.mp4',
'filesize':None
}
file_path=os.path.join(head['filepath'],head['filename'])
filesize=os.path.getsize(file_path)
head['filesize']=filesize #发送字典用json
json_head=json.dumps(head) #字典转化为字符串
bytes_head=json_head.encode('utf-8') #字符串转bytes
#计算head 长度
head_len=len(bytes_head) #报头的长度·1
pack_len=struct.pack('i',head_len)
sk.send(pack_len)
sk.send(bytes_head)
with open(file_path,'rb') as f:
while filesize:
if filesize>=buffer:
content=f.read(buffer) #每次读出文件大小
sk.send(content)
filesize-=buffer
else:
content=f.read(filesize)
sk.send(content)
break
sk.close()