zoukankan      html  css  js  c++  java
  • 网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例

    UDP协议 (了解)
    称之为数据包协议,又称不可靠协议。

    特点:
      1) 不需要建立链接。
      2) 不需要知道对方是否收到。
      3) 数据不安全
      4) 传输速度快
      5)能支持并发
      6) 不会粘包
      7) 无需先启动服务端再启动客户端

    优点:
      - 传输速度快
      - 能支持并发
      - 不会粘包

    缺点:
      - 数据不安全, 容易丢失

    应用场景: 早期的QQ聊天室。

    # server端
    import socket
    
    # socket.SOCK_DGRAM ---> UPD协议
    server = socket.socket(type=socket.SOCK_DGRAM)
    # 服务端需要绑定一个地址,让别人知道你在哪里
    server.bind(
        ('127.0.0.1', 9002)
    )
    
    while True:
    
        # 发送数据给服务端的用户地址
        data, addr = server.recvfrom(1024)
        print(addr)
        print(data)
        # msg = input('Server ---> Client:').encode('utf-8')
    
        # 无论服务端还是客户端,发送消息时,都必须知道对方是谁
        # server.sendto(msg, addr)
    # client端
    import socket
    
    client = socket.socket(type=socket.SOCK_DGRAM)
    
    address = ('127.0.0.1', 9002)
    
    while True:
        msg = input('Client ---> Server:').encode('utf-8')
    
        client.sendto(msg, address)
    
        # data, addr = client.recvfrom(1024)
        #
        # print(data)

    - TCP协议(称为流式协议):

      优点:
        - 数据安全

      缺点:
        - 传输速度慢
        - 粘包

    面试: TCP与UDP的区别, 简述优缺点即可。(*******)

    TCP局域网客户端与服务端上传下载电影示例

    文件夹位置:

    '''  server
    6.实现需求
        - 准备一堆电影,存放在一个文件夹中。
    
        - 需求:
            - 1)客户端上传到服务端
                1.让用户选择的上传的电影
                2.服务端接收电影并保存
    
            - 2)客户端下载服务端中的电影
                1.客户端让服务端返回可下载电影
                2.客户端选择下载的电影并下载
    '''
    import socket
    import struct
    import json
    import os
    
    movie_path = r'D:oldboy_edupython课堂内容day291 作业讲解server_movie'
    
    def recv(conn):
        headers = conn.recv(4)
        bytes_len = struct.unpack('i', headers)[0]
        json_data = conn.recv(bytes_len).decode('utf8')
        back_dic = json.loads(json_data)
        print('收到服务端数据: ', back_dic)
        return back_dic
    
    def send(msg,conn):
        json_bytes = json.dumps(msg).encode('utf8')
        headers = struct.pack('i', len(json_bytes))
        conn.send(headers)
        conn.send(json_bytes)
    
    server = socket.socket()
    server.bind(('127.0.0.1',9000))
    server.listen(5)
    
    while True:
        conn,addr = server.accept()
        while True:
            try:
                # 1、接收客户端发送的消息
                back_dic=recv(conn)
                _type = back_dic.get('type')
    
                if _type == 'upload':
                    # 4.组织服务端存放上传电影的目录
                    movie_size = back_dic.get('movie_size')
                    movie_name = back_dic.get('movie_name')
                    download_path = r'D:oldboy_edupython课堂内容day291 作业讲解server_save_movie'
                    # 保存电影文件路径
                    movie_download_path = os.path.join(download_path,movie_name)
    
                    recv_data = 0
                    with open(movie_download_path,'wb')as f:
                        # 一次性接收电影所有数据,有可能撑爆内存
                        # movie_data = conn.recv(movie_size)
                        # f.write(movie_data)
    
                        # 一点一点接收
                        while recv_data < movie_size:
                            data = conn.recv(1024)
                            f.write(data)
                            recv_data+=len(data)
    
                elif _type == 'download':
                    movie_list = os.listdir(movie_path)
                    send_dic = {'movie_list':movie_list}
                    # 服务端发送给客户端的字典
                    send(send_dic, conn)
    
                    # 服务端接收客户端发送过来的字典
                    back_dic=recv(conn)
    
                    movie_name = back_dic.get('movie_name')
                    # 拼接需要下载的电影文件路径
                    movie_choose_path = os.path.join(movie_path,movie_name)
                    movie_size= os.path.getsize(movie_choose_path)
                    # 组织需要发送给客户端的电影数据
                    send_dic = {'movie_size':movie_size}
    
                    send(send_dic,conn)
                    # json数据发送完毕后,紧接着发送真实电影数据
                    with open(movie_choose_path,'rb')as f:
                        for line in f:
                            conn.send(line)
    
            except Exception 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',9000))
    
    movie_path = r'D:oldboy_edupython课堂内容day291 作业讲解client_movie'
    
    def send(msg,client):
        json_bytes = json.dumps(msg).encode('utf8')
        headers = struct.pack('i', len(json_bytes))
        client.send(headers)
        client.send(json_bytes)
    
    def recv(client):
        headers = client.recv(4)
        bytes_len = struct.unpack('i', headers)[0]
        json_data = client.recv(bytes_len).decode('utf8')
        back_dic = json.loads(json_data)
        print('收到服务端数据: ', back_dic)
        return back_dic
    
    while True:
        # 打印功能编号,让用户选择功能
        print('''
        1.上传
        2.下载
        q.退出
        ''')
        choice = input('请输入功能编号:').strip()
        if choice == 'q':
            break
        elif choice == '1':
            # 1) 组织报头数据,并打包
            # 上传电影功能
            movie_list = os.listdir(movie_path)
            while True:
                for index,movie_name in enumerate(movie_list):
                    print(index,movie_name)
                choice = input('输入需要上传的电影编号:').strip()
                if not choice.isdigit():
                    continue
                choice = int(choice)
                if not choice in range(len(movie_list)):
                    continue
                movie_name = movie_list[choice]
                # 拼接上传电影的路径
                upload_movie_path= os.path.join(movie_path,movie_name)
                # os.path.getsize(): 获取文件大小
                movie_size = os.path.getsize(upload_movie_path)
                # 客户端发送给服务端的字典
                send_dic = {
                    'type':'upload',
                    'movie_name':movie_name,
                    'movie_size':movie_size
                }
                send(send_dic,client)
                # 开始发送上传的电影
                with open(upload_movie_path,'rb')as f:
                    # 一次性发送: 内存资源占用过大
                    # data = f.read()
                    # client.send(data)
    
                    # 一点一点发送
                    for line in f:
                        client.send(line)
    
        elif choice == '2':
            # 下载电影功能
            # 1.客户端发送消息给服务端
            send_dic = {'type':'download'}
            send(send_dic,client)
    
            # 2.客户端接收服务端返回的消息
            back_dic=recv(client)
            movie_list = back_dic.get('movie_list')
            # 4.循环打印需要下载的电影列表
            while True:
                for index,movie_name in enumerate(movie_list):
                    print(index,movie_name)
                choice = input('请输入上传电影编号:').strip()
                if not choice.isdigit():
                    continue
                choice = int(choice)
                if choice not in range(len(movie_list)):
                    continue
                movie_name = movie_list[choice]
                # 发送需要下载电影的字典给服务端
                send_dic = {'movie_name':movie_name}
                send(send_dic,client)
    
                # 客户端接收服务单发送过来的电影字典
                back_dic = recv(client)
                # 接收电影的数据大小
                movie_size = back_dic.get('movie_size')
    
                movie_save_path = os.path.join(movie_path,movie_name)
    
                recv_data = 0
                # 开始接收真实电影数据
                with open (movie_save_path,'wb')as f:
                    while recv_data < movie_size:
                        data = client.recv(1024)
                        f.write(data)
                        recv_data += len(data)
    
    client.close()
  • 相关阅读:
    HDU1575--Tr A(矩阵快速幂)
    HDU 2147--HDU 2147(博弈)--我可能做了假题。。。
    新年第一发--HDU1848--Fibonacci again and again(SG函数)
    【转】你真的会二分查找吗?
    windows与ubuntu双系统的安装
    bestcoder#9--1001--Lotus and Characters
    PC端的混合应用通讯问题
    JS构造函数详解
    JS的prototype的共享机制分析
    使用a标签直接下载图片
  • 原文地址:https://www.cnblogs.com/ludingchao/p/11997475.html
Copyright © 2011-2022 走看看