网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例

Posted ludingchao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程 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 = rD: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 = rD: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 = rD: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()

 

以上是关于网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例的主要内容,如果未能解决你的问题,请参考以下文章

网络协议TFTP

当UDP协议客户端给TCP协议服务器发数据会发生什么

第6课.网络编程

网络编程-socket之TCP协议开发客户端和服务端通信

面试补缺:TCP协议与UDP协议总结

NFS共享服务