TCP大文件发送案例以及UDP介绍

基于TCP的大文件发送

#server服务端
import struct
import json
import os
import socket

server = socket.socket()  # 默认TCP协议
server.bind(('127.0.0.1',8080))  # 传入IP和端口
server.listen(5)  # 限制半连接池的数量

while True:
    conn,addr = server.accept()  # conn是连接,addr是地址,accept就是阻塞,等待一下,等客户端连接
    while True:
        try:
            header_dict = conn.recv(4) # 接收一个字典的报头
            dict_size = struct.unpack('i',header_dict)[0]  # 解包得到字典的长度
            dict_bytes = conn.recv(dict_size) # 接收一个字典
            dict_json = json.loads(dict_bytes.decode('utf-8'))  # 将字典解码并反序列化
            total_size = dict_json.get('file_size') #拿出字典中真实数据的大小
            recv_size = 0
            with open(dict_json.get('file_name'),'wb') as f:
                while recv_size < total_size:
                    data = conn.recv(1024)  # 接收真实的数据
                    f.write(data)  # 将数据写入文件
                    recv_size += len(data)
                print('上传成功')
        except ConnectionResetError as e:  # 捕获客户端断开产生的错误
            print(e)
            break
    conn.close()  # 关闭客户端套接字
#client客户端
import socket
import struct
import json
import os

client = socket.socket()
client.connect(('127.0.0.1',8080))
while True:
    MOVIE_DIR = r'D:\Program Files\feiq\work\untitled\work\sp'  # 找到文件路径
    movie_list = os.listdir(MOVIE_DIR) # 将文件夹下的文件名放到列表里
    for i,movie in enumerate(movie_list,1):  # 给列表中的文件名加上序号,从1开始
        print(i,movie)
    choice = input('请输入电影序号>>>:')
    if choice.isdigit():
        choice = int(choice) - 1
        if choice in range(0,len(movie_list)):
            path = movie_list[choice]  # 根据用户的选择,拿到文件名
            file_path = os.path.join(MOVIE_DIR,path)  # 拼接文件名的路径
            file_size = os.path.getsize(file_path)  # 获得该文件的大小
            res_d = {
                'file_name':path,
                'file_size':file_size,
                'msg':'注意身体健康'
            }  # 将文件名,大小以及一些其他信息存放在字典里
            json_d = json.dumps(res_d)  # 将字典转换成json格式的数据
            json_bytes = json_d.encode('utf-8')  # 将这个数据变成二进制
            header = struct.pack('i',len(json_bytes))  # 打包一个报头,报头的内容是字典的长度
            client.send(header)  # 发送一个报头
            client.send(json_bytes)  # 发送这个字典
            with open(file_path,'rb') as f:  # 找到给文件并准备发送
                for line in f:
                    client.send(line)  # 循环取出数据并发送
        else:
            print('not in range')
    else:
        print('must be a number')

UDP通信

特点:数据报协议(自带报头),没有双向通道,通信过程类似于发短信。

1.udp协议客户端允许发空

2.udp协议不会粘包

3.udp协议支持并发

***允许发空和不会粘包的原因都是因为基于数据报协议,自带了报头

UDP协议的基本使用:
#服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)  # UDP协议
server.bind(('127.0.0.1',8080))
#UDP不需要设置半连接池,它也没有半连接池的概念

#因为没有双向通道,不需要accept,直接就到通信循环
while True:
    data,addr = server.recvfrom(1024)
    print('数据:',data)  # 客户端发来的消息
    print('地址:',addr)  # 客户端的地址
    server.sendto(data.upper(),addr)


#客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
# 不需要建立连接,直接进入通信循环
server_address = ('127.0.0.1',8080)
while True:
    client.sendto(b'hello',server_address)
    data,addr = client.recvfrom(1024)
    print('服务端发来的数据',data)
    print('服务端的地址',addr)

简易版本的QQ

#服务端:
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))

while True:
    data,addr = server.recvfrom(1024)
    print(data.decode('utf-8'))
    msg = input('>>>:')
    server.sendto(msg.encode('utf-8'),addr)


#客户端:
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)

while True:
    msg = input('>>>:')
    res = '来自客户端1的消息:%s'%msg
    client.sendto(res.encode('utf-8'),server_address)
    data,server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'))

利用socketserver完成并发

#服务器
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data, sock = self.request
            print(self.client_address)  # 客户端地址
            print(data.decode('utf-8'))
            sock.sendto(data.upper(), self.client_address)

if __name__ == '__main__':
"""只要有客户端连接,会自动交给自定义类中的handle方法去处理"""    
    server = socketserver.ThreadingUDPServer(('127.0.0.1',8080), MyServer)
    server.serve_forever()  # 启动该服务对象

#客户端
import socket
import time

client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)

while True:
    client.sendto(b'hello',server_address)
    data,addr = client.recvfrom(1024)
    print(data.decode('utf-8'),addr)
    time.sleep(1)  # 睡眠1秒,让服务端有反馈的时间

并发:看起来像同时运行的

并行:真正意义上的同时运行

posted @ 2019-08-08 20:31  云上fly  阅读(348)  评论(0编辑  收藏  举报