编程语言
首页 > 编程语言> > day32_python

day32_python

作者:互联网

参考Eva_J的博客,原文连接:https://www.cnblogs.com/Eva-J/p/7277026.html

主要知识

# 应用层协议ftp文件传输,http网页,smtp邮件相关的协议,https更加安全
'''
OSI模型
'''
# server
'''
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8000))
sk.listen()
conn, addr = sk.accept()
while 1:
    cmd = input('>>>')
    if cmd == 'q':
        conn.send(b'q')
        break
    conn.send(cmd.encode('gbk'))
    res = conn.recv(1024).decode('gbk')
    print(res)

conn.close()
sk.close()
'''
# client端
'''
import subprocess
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 8000))
sk.recv(1024).decode('gbk')
while 1:
    cmd = sk.recv(1024).decode('gbk')
    if cmd == 'q':
        break
    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    sk.send(res.stderr.read())
    sk.send(res.stdout.read())
sk.close()
'''
# 优化算法,连续的小数据包会被合并,已经被接收的就无法从缓存中读取了
# 多个send小数据连在一起,会发生黏包现象。
# tcp内部的优化算法是在短暂时间内会发生,加上一定时间的延时就好了,0.01s就可以
# 解决粘包问题的方式
# struct模块
'''
该模块可以把一个类型,如数字,转成固定长度的bytes
import struct
ret = struct.pack('i', 4096)  # 'i'即将要将一个数字专户为固定字节的bytes类型
print(ret)
num = struct.unpack('i',ret)
print(num[0])
发送数据的时候,先发送长度,先接收一个长度
'''
# 管道中的数据只能取一次,类似于队列
'''
import queue
q=  queue.Queue()
q.put(1)  # 向队列中放数
print(q.qsize())
print(q.get())  # 取一次就pop
print(q.qsize())
在网络上传输的所有数据都叫做数据包,数据包里的所有的数据都叫报文
报文里面有ip、mac、端口号
报文根据协议有报头,都有报头
'''
# 定制报文
head = {'filename': 'demo', 'filesize': 409600,
        'filetype': 'txt', 'filepath': r'\usr\bin'}
# 报头的长度 先接收4个字节
# 根据4个字节获取报头
# 根据报头获取filesize,然后根据filesize接收文件
# 狭义上的协议网络协议是通信计算机双方必须共同遵从的一组约定。
'''
如怎么样建立连接、怎么样互相识别等。
只有遵守这个约定,计算机之间才能相互通信交流。
协议往往分成几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。

'''

文件的上传下载

server端

import socket
import struct
import json
sk = socket.socket()
sk.bind(('127.0.0.1', 8890))
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']
print('正在启动···')
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

conn.close()
sk.close()

client端

import socket
import os
import json
import struct
sk = socket.socket()
buffer = 1024
sk.connect(('127.0.0.1', 8890))
head = {'filepath': r'F:\视频\internet',
        'filename': r'千谎百计第一季-01.mp4', 'filesize': None}
filepath = os.path.join(head['filepath'], head['filename'])
filesize = os.path.getsize(filepath)
head['filesize'] = filesize
json_head = json.dumps(head)  # 字典转成了字符串
byte_head = json_head.encode('utf-8')  # 字符串转bytes
head_len = len(byte_head)
pack_len = struct.pack('i', head_len)
sk.send(pack_len)  # 先发报头的长度
sk.send(byte_head)  # 再发送bytes类型的报头
print('正在启动···')
with open(filepath, '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
print('已发完')
sk.close()

标签:head,socket,python,day32,sk,filesize,import,conn
来源: https://www.cnblogs.com/Come3/p/15350449.html