• ~~网络编程(七):文件处理~~


    进击のpython

    *****

    网络编程——文件处理


    有了上次的模板之后啊

    我们就应该可以对于文件进行操作了

    对于文件的操作就是上传和下载

    而在上文上我也提到了,上文写的是一个模板

    既然是模板,就应该是拿过来稍加改动就能完成我的要求

    好,分析一下吧

    在刚开始的时候是这样的

    客户端键入命令

    order = input() # get a.txt
    

    然后把这条命令的字节形式,编码为gbk的形式传给服务端

    phone.send(order.encode("gbk"))
    

    然后服务端开始接收,并进行解码

    order = phone.recv(1024)
    filename = order.decode("gbk").split(" ")[1]
    

    我拿到的就是想要下载的文件名

    然后就进行报头的设计,就可以直接用模板

    顺便说一下如何获取文件的大小?

    os.path.getsize(文件名)
    

    发完了报头就应该传输数据了是吧

    因为字节才能在管道传输,所以我选择的打开方式是rb

    打开文件之后,别一口气全读出来,万一很大呢?所以一行一行循环读

    with open(filename,"rb") as f:
        for i in f.read():
            connet.send(i)
    

    好了,这面发送了,你那面就该接收了吧

    表面上是我把包丢给你了,实际上是你在原地新建了一个文件

    然后把数据写入了

    那我就在本地写个文件被,然后将收到的东西都写进来,怎么写?还是字节啊wb

    with open(filename,"wb") as f:
        recv_size = 0
        while recv_size<re_len:
            res = phone.recv(1024)
            f.write(res)
            recv_size+=len(res)
    

    是吧!大约是这个套路吧

    那整合一下吧

    # 客户端
    import json
    import socket
    
    # 买手机
    import struct
    
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 拨号
    phone.connect(("127.0.0.1", 8080))
    
    # 发收信息
    while 1:
        order = input(">>>")
        phone.send(order.encode("gbk"))
        res = phone.recv(4)
        re_msg = struct.unpack("i", res)[0]
        msg = phone.recv(re_msg)
        msg = msg.decode("gbk")
        msg = json.loads(msg)
        re_len = msg["file_size"]
        re_size = 0
        r = b""  # 我传过来的是字节模式
        with open("b", "wb") as f:
            recv_size = 0
            while recv_size < re_len:
                res = phone.recv(1024)
                f.write(res)
                recv_size += len(res)
        print(f'打印成功')
    
    connet.close()
    # 关闭
    phone.close()
    
    
    # 服务端
    import json
    import os
    import socket
    import struct
    import subprocess
    
    # 买手机
    
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 绑定手机卡
    phone.bind(("127.0.0.1", 8080))
    phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 开机
    phone.listen(5)
    
    # 等电话
    connet, client_addr = phone.accept()
    
    # 收发消息
    while 1:
        try:
            order = connet.recv(1024)
            filename = order.decode("gbk").split(" ")[1]
            # obj = subprocess.Popen(order.decode("gbk"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            # stdout = obj.stdout.read()
            # stderr = obj.stderr.read()
    
            dic = {
                "file_name": filename,
                "MD5": "XXXXXXXXXXXXXXXX",
                'file_size': os.path.getsize(filename)
            }
            head = json.dumps(dic)
            head = head.encode("gbk")
            res = struct.pack("i", len(head))
            connet.send(res)
            connet.send(head)
    
            with open(filename) as f:
                for line in f.read():
                    print(line)
                    connet.send(bytes(line, encoding="gbk"))
        except ConnectionResetError:
            break
    
    # 挂电话
    connet.close()
    
    # 关机
    phone.close()
    
    
    

    但是你不觉得我写的太乱了吗??

    所以,我们用函数写!


    首先前面的全局变量是不适合放进函数里的是吧

    而下面的代码块是不是都是执行语句

    所以我们可以把这些代码整体进行缩进

    def run():
        phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # 绑定手机卡
        phone.bind(("127.0.0.1", 8080))
        phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 开机
        phone.listen(5)
    
        # 等电话
        connet, client_addr = phone.accept()
    
        # 收发消息
        while 1:
            try:
                order = connet.recv(1024)
                filename = order.decode("gbk").split(" ")[1]
                # obj = subprocess.Popen(order.decode("gbk"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                # stdout = obj.stdout.read()
                # stderr = obj.stderr.read()
    
                dic = {
                    "file_name": filename,
                    "MD5": "XXXXXXXXXXXXXXXX",
                    'file_size': os.path.getsize(filename)
                }
                head = json.dumps(dic)
                head = head.encode("gbk")
                res = struct.pack("i", len(head))
                connet.send(res)
                connet.send(head)
    
                with open(filename) as f:
                    for line in f.read():
                        print(line)
                        connet.send(bytes(line, encoding="gbk"))
            except ConnectionResetError:
                break
    
        # 挂电话
        connet.close()
    
        # 关机
        phone.close()
    

    然后我们再来看,是不是中间有个下载的功能啊

    然后我们默认传过来的命令是get是吧

    所以这个是不是也可以封装成一个函数?

    封装完之后是不是应该传参数啊

    def down(connet, filename):
        dic = {
            "file_name": filename,
            "MD5": "XXXXXXXXXXXXXXXX",
            'file_size': os.path.getsize(filename)
        }
        head = json.dumps(dic)
        head = head.encode("gbk")
        res = struct.pack("i", len(head))
        connet.send(res)
        connet.send(head)
    
        with open(filename) as f:
            for line in f.read():
                print(line)
                connet.send(bytes(line, encoding="gbk"))
    

    最后是不是应该再加个点睛之笔啊!

    if __name__ == '__main__':
        run()
    

    那客户端是不是也可以封装函数啊

    远离其实都差不多,就不再赘述了,直接放代码

    def get(phone):
        res = phone.recv(4)
        re_msg = struct.unpack("i", res)[0]
        msg = phone.recv(re_msg)
        msg = msg.decode("gbk")
        msg = json.loads(msg)
        re_len = msg["file_size"]
        with open("b", "wb") as f:
            recv_size = 0
            while recv_size < re_len:
                res = phone.recv(1024)
                f.write(res)
                recv_size += len(res)
        print(f'打印成功')
    
    def run():
        phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        phone.connect(("127.0.0.1", 8080))
        while 1:
            order = input(">>>")
            phone.send(order.encode("gbk"))
            order = order.split()
            if order[0] == "get":
                get(phone)
    
            phone.close()
    

    最后一样,注入灵魂

    if __name__ == '__main__':
        run()
    

    最后整理一下:

    # 客户端
    import json
    import socket
    
    # 买手机
    import struct
    
    
    def get(phone):
        res = phone.recv(4)
        re_msg = struct.unpack("i", res)[0]
        msg = phone.recv(re_msg)
        msg = msg.decode("gbk")
        msg = json.loads(msg)
        re_len = msg["file_size"]
        with open("b.mp4", "wb") as f:
            recv_size = 0
            while recv_size < re_len:
                res = phone.recv(1024)
                f.write(res)
                recv_size += len(res)
        print(f'打印成功')
    
    
    def put(phone):
        pass
    
    
    def run():
        phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        phone.connect(("127.0.0.1", 8080))
        while 1:
            order = input(">>>")
            phone.send(order.encode("gbk"))
            order = order.split()
            if order[0] == "get":
                get(phone)
            elif order[0] == "put":
                put(phone)
    
            phone.close()
    
    
    if __name__ == '__main__':
        run()
    
    
    # 服务端
    import json
    import os
    import socket
    import struct
    import subprocess
    
    
    def down(connet, filename):
        dic = {
            "file_name": filename,
            "MD5": "XXXXXXXXXXXXXXXX",
            'file_size': os.path.getsize(filename)
        }
        head = json.dumps(dic)
        head = head.encode("gbk")
        res = struct.pack("i", len(head))
        print(len(head))
        connet.send(res)
        connet.send(head)
    
        with open(filename, "rb") as f:
            for line in f.readlines():
                connet.send(line)
    
    
    def put(connet, filename):
        pass
    
    
    def run():
        phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # 绑定手机卡
        phone.bind(("127.0.0.1", 8080))
        phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 开机
        phone.listen(5)
    
        # 等电话
        connet, client_addr = phone.accept()
    
        # 收发消息
        while 1:
            try:
                order = connet.recv(1024)
                filename = order.decode("gbk").split(" ")[1]
                # obj = subprocess.Popen(order.decode("gbk"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                # stdout = obj.stdout.read()
                # stderr = obj.stderr.read()
                if order.decode("gbk").split(" ")[0] == "get":
                    down(connet, filename)
                elif order.decode("gbk").split(" ")[0] == "put":
                    put(connet, filename)
            except ConnectionResetError:
                break
    
        # 挂电话
        connet.close()
    
        # 关机
        phone.close()
    
    
    if __name__ == '__main__':
        run()
    
    

    建议你们可以自己把另一个功能补上!

    但是吧,其实这么写还不太好!

    因为我们学过面向对象

    所以我们也可以用面向对象来处理这个问题!


    关于面向对象,就是将所有的方法进行打散,然后把每个方法都进行封装

    最后自己调用自己写的方法就行

    这一段就直接放代码了(关注一下反射的使用)

    # 服务端
    import socket
    import struct
    import json
    import subprocess
    import os
    class MYTCPServer:
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        allow_reuse_address = False
        max_packet_size = 8192
        coding='utf-8'
        request_queue_size = 5
        server_dir='file_upload'
        def __init__(self, server_address, bind_and_activate=True):
            """Constructor.  May be extended, do not override."""
            self.server_address=server_address
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if bind_and_activate:
                try:
                    self.server_bind()
                    self.server_activate()
                except:
                    self.server_close()
                    raise
        def server_bind(self):
            """Called by constructor to bind the socket.
            """
            if self.allow_reuse_address:
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind(self.server_address)
            self.server_address = self.socket.getsockname()
        def server_activate(self):
            """Called by constructor to activate the server.
            """
            self.socket.listen(self.request_queue_size)
        def server_close(self):
            """Called to clean-up the server.
            """
            self.socket.close()
        def get_request(self):
            """Get the request and client address from the socket.
            """
            return self.socket.accept()
        def close_request(self, request):
            """Called to clean up an individual request."""
            request.close()
        def run(self):
            while True:
                self.conn,self.client_addr=self.get_request()
                print('from client ',self.client_addr)
                while True:
                    try:
                        head_struct = self.conn.recv(4)
                        if not head_struct:break
                        head_len = struct.unpack('i', head_struct)[0]
                        head_json = self.conn.recv(head_len).decode(self.coding)
                        head_dic = json.loads(head_json)
                        print(head_dic)
                        #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
                        cmd=head_dic['cmd']
                        if hasattr(self,cmd):
                            func=getattr(self,cmd)
                            func(head_dic)
                    except Exception:
                        break
        def put(self,args):
            file_path=os.path.normpath(os.path.join(
                self.server_dir,
                args['filename']
            ))
            filesize=args['filesize']
            recv_size=0
            print('----->',file_path)
            with open(file_path,'wb') as f:
                while recv_size < filesize:
                    recv_data=self.conn.recv(self.max_packet_size)
                    f.write(recv_data)
                    recv_size+=len(recv_data)
                    print('recvsize:%s filesize:%s' %(recv_size,filesize))
    tcpserver1=MYTCPServer(('127.0.0.1',8080))
    tcpserver1.run()
    
    # 客户端
    import socket
    import struct
    import json
    import os
    class MYTCPClient:
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        allow_reuse_address = False
        max_packet_size = 8192
        coding='utf-8'
        request_queue_size = 5
        def __init__(self, server_address, connect=True):
            self.server_address=server_address
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if connect:
                try:
                    self.client_connect()
                except:
                    self.client_close()
                    raise
        def client_connect(self):
            self.socket.connect(self.server_address)
        def client_close(self):
            self.socket.close()
        def run(self):
            while True:
                inp=input(">>: ").strip()
                if not inp:continue
                l=inp.split()
                cmd=l[0]
                if hasattr(self,cmd):
                    func=getattr(self,cmd)
                    func(l)
        def put(self,args):
            cmd=args[0]
            filename=args[1]
            if not os.path.isfile(filename):
                print('file:%s is not exists' %filename)
                return
            else:
                filesize=os.path.getsize(filename)
            head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
            print(head_dic)
            head_json=json.dumps(head_dic)
            head_json_bytes=bytes(head_json,encoding=self.coding)
            head_struct=struct.pack('i',len(head_json_bytes))
            self.socket.send(head_struct)
            self.socket.send(head_json_bytes)
            send_size=0
            with open(filename,'rb') as f:
                for line in f:
                    self.socket.send(line)
                    send_size+=len(line)
                    print(send_size)
                else:
                    print('upload successful')
    client=MYTCPClient(('127.0.0.1',8080))
    client.run()
    

    好,最后这一种就是面向对象的写法了

    至此,TCP就完事了,接下来就是UDP的天下了!


    *有点东西*
    *继续深究*
  • 相关阅读:
    使用 git 托管代码
    转载自网络大神
    i18n 国际化
    转自知乎大神---什么是 JS 原型链?
    转自知乎大神----JS 闭包是什么
    转自知乎大神----JS 的 new 到底是干什么的?
    转载自知乎大神---this 的值到底是什么?一次说清楚
    sql查看本机IP地址
    Python 编码规范(Google)
    Python在mysql中进行操作是十分容易和简洁的
  • 原文地址:https://www.cnblogs.com/jevious/p/11327333.html
Copyright © 2020-2023  润新知