zoukankan      html  css  js  c++  java
  • 进击的Python【第八章】:动态导入模块、断言、socket开发之SSH,FTP

    一、动态导入模块

    知道一个模块名的字符串形式,通过字符串来导入模块

    1 mod = __import__("lib.aa")
    2 print(mod)
    3 
    4 instance = getattr(mod.aa, "C")
    5 
    6 obj = instance()
    7 print(obj.name)

    __import__("lib.aa")看起来是导入了lib.aa,实际上只导入了lib

    下面是官方建议的用法

    1 import importlib
    2 importlib.import_module("lib.aa") #这里就直接导入了lib.aa

    二、断言

    import importlib
    importlib.import_module("lib.aa")
    
    obj = aa.C()
    
    assert type(obj.name) is str #assert就是断言
    print("dddd")

    上面表示我断定obj.name就是str,如果正确程序往下走,如果错误直接报错AssertionError

    三、通过socket实现SSH功能

    server端:

     1 import socket ,os,time
     2 server = socket.socket()
     3 server.bind(('localhost',9999) )
     4 
     5 server.listen()
     6 
     7 while True:
     8     conn, addr = server.accept()
     9     print("new conn:",addr)
    10     while True:
    11         print("等待新指令")
    12         data = conn.recv(1024)
    13         if not data:
    14             print("客户端已断开")
    15             break
    16         print("执行指令:",data)
    17         cmd_res = os.popen(data.decode()).read() #接受字符串,执行结果也是字符串
    18         print("before send",len(cmd_res))
    19         if len(cmd_res) ==0:
    20             cmd_res = "cmd has no output..."
    21 
    22         conn.send( str(len(cmd_res.encode())).encode("utf-8")    )     #先发大小给客户端
    23         #time.sleep(0.5) #lowb防粘包
    24         client_ack = conn.recv(1024) #等待客户端应答,高端防粘包
    25         conn.send(cmd_res.encode("utf-8"))
    26         print("send done")
    27         os.path.isfile()
    28         os.stat("sock")
    29 server.close()
    30 

    client端:

     1 import socket
     2 client = socket.socket()
     3 
     4 client.connect(('localhost',9999))
     5 
     6 while True:
     7     cmd = input(">>:").strip()
     8     if len(cmd) == 0: continue
     9     client.send(cmd.encode("utf-8"))
    10     cmd_res_size = client.recv(1024) ##接受命令结果的长度
    11     print("命令结果大小:",cmd_res_size)
    12     client.send("准备好接受".encode("utf-8")) #防粘包
    13     received_size = 0
    14     received_data = b''
    15     while received_size < int(cmd_res_size.decode()) :
    16         data = client.recv(1024)
    17         received_size += len(data) #每次收到的有可能小于1024,所以必须用len判断
    18         #print(data.decode())
    19         received_data += data
    20     else:
    21         print("cmd res receive done...",received_size)
    22         print(received_data.decode())
    23 
    24 
    25 client.close()

    四、通过socket实现FTP功能

    client端:

     1 import socket
     2 import hashlib
     3 
     4 client = socket.socket()
     5 
     6 client.connect(('localhost', 9999))
     7 
     8 while True:
     9     cmd = input(">>:").strip()
    10     if len(cmd) == 0: continue
    11     if cmd.startswith("get"):
    12         client.send(cmd.encode())
    13         server_response = client.recv(1024)
    14         print("servr response:", server_response)
    15         client.send(b"ready to recv file")
    16         file_total_size = int(server_response.decode())
    17         received_size = 0
    18         filename = cmd.split()[1]
    19         f = open(filename + ".new", "wb")
    20         m = hashlib.md5()
    21 
    22         while received_size < file_total_size:
    23             if file_total_size - received_size > 1024:  # 要收不止一次
    24                 size = 1024
    25             else:  # 最后一次了,剩多少收多少
    26                 size = file_total_size - received_size
    27                 print("last receive:", size)
    28 
    29             data = client.recv(size)
    30             received_size += len(data)
    31             m.update(data) # 记录MD5
    32             f.write(data)
    33             # print(file_total_size,received_size)
    34         else:
    35             new_file_md5 = m.hexdigest()
    36             print("file recv done", received_size, file_total_size)
    37             f.close()
    38         server_file_md5 = client.recv(1024)
    39         print("server file md5:", server_file_md5) # 输出服务端文件MD5
    40         print("client file md5:", new_file_md5) # 输出传过来的文件的MD5
    41 
    42 client.close()

    server端:

     1 import hashlib
     2 import socket ,os,time
     3 server = socket.socket()
     4 server.bind(('0.0.0.0',9999) )
     5 server.listen()
     6 while True:
     7     conn, addr = server.accept()
     8     print("new conn:",addr)
     9     while True:
    10         print("等待新指令")
    11         data = conn.recv(1024)
    12         if not data:
    13             print("客户端已断开")
    14             break
    15         cmd,filename = data.decode().split()
    16         print(filename)
    17         if os.path.isfile(filename):
    18            f = open(filename,"rb")
    19            m = hashlib.md5()
    20            file_size = os.stat(filename).st_size
    21            conn.send( str(file_size).encode() ) #send file size
    22            conn.recv(1024) #wait for ack
    23            for line in f:
    24               m.update(line)
    25               conn.send(line)
    26            print("file md5", m.hexdigest())
    27            f.close()
    28            conn.send(m.hexdigest().encode()) #send md5
    29         print("send done")
    30 
    31 server.close()

    五、通过SocketServer实现多并发

    The socketserver module simplifies the task of writing network servers.

    There are four basic concrete server classes:

    1 class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    This uses the Internet TCP protocol, which provides for continuous streams of data between the client and server. If bind_and_activate is true, the constructor automatically attempts to invoke server_bind() andserver_activate(). The other parameters are passed to the BaseServer base class.

    1 class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    This uses datagrams, which are discrete packets of information that may arrive out of order or be lost while in transit. The parameters are the same as for TCPServer.

    1 class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
    2 class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)

    These more infrequently used classes are similar to the TCP and UDP classes, but use Unix domain sockets; they’re not available on non-Unix platforms. The parameters are the same as for TCPServer.

    These four classes process requests synchronously; each request must be completed before the next request can be started. This isn’t suitable if each request takes a long time to complete, because it requires a lot of computation, or because it returns a lot of data which the client is slow to process. The solution is to create a separate process or thread to handle each request; the ForkingMixIn and ThreadingMixIn mix-in classes can be used to support asynchronous behaviour.

    There are five classes in an inheritance diagram, four of which represent synchronous servers of four types:

    +------------+
    | BaseServer |
    +------------+
          |
          v
    +-----------+        +------------------+
    | TCPServer |------->| UnixStreamServer |
    +-----------+        +------------------+
          |
          v
    +-----------+        +--------------------+
    | UDPServer |------->| UnixDatagramServer |
    +-----------+        +--------------------+


    创建一个socketserver 至少分以下几步:

    1. First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests.   
    2. Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.
    3. Then call the handle_request() orserve_forever() method of the server object to process one or many requests.
    4. Finally, call server_close() to close the socket.

    基本的socketserver代码

     1 import socketserver
     2 
     3 class MyTCPHandler(socketserver.BaseRequestHandler):
     4     """
     5     The request handler class for our server.
     6 
     7     It is instantiated once per connection to the server, and must
     8     override the handle() method to implement communication to the
     9     client.
    10     """
    11 
    12     def handle(self):
    13         # self.request is the TCP socket connected to the client
    14         self.data = self.request.recv(1024).strip()
    15         print("{} wrote:".format(self.client_address[0]))
    16         print(self.data)
    17         # just send back the same data, but upper-cased
    18         self.request.sendall(self.data.upper())
    19 
    20 if __name__ == "__main__":
    21     HOST, PORT = "localhost", 9999
    22 
    23     # Create the server, binding to localhost on port 9999
    24     server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    25 
    26     # Activate the server; this will keep running until you
    27     # interrupt the program with Ctrl-C
    28     server.serve_forever()

    上面的代码虽然使用了socketserver,但是依然不能实现多并发,我们要想实现多并发通信,需要用到下面这些多并发类

    class socketserver.ForkingTCPServer

    class socketserver.ForkingUDPServer

    class socketserver.ThreadingTCPServer

    class socketserver.ThreadingUDPServer

    我们只需要把上面的代码中的

    1 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)

    替换为:

    1 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)

    就可以实现多线程多并发了

    下面我们举个栗子:

     1 import socketserver
     2 
     3 class MyTCPHandler(socketserver.BaseRequestHandler):
     4     def handle(self):
     5         while True:
     6             try:
     7                 self.data = self.request.recv(1024).strip()
     8                 print("{} wrote:".format(self.client_address[0]))
     9                 print(self.data)
    10                 self.request.send(self.data.upper())
    11             except ConnectionResetError as e:
    12                 print("err",e)
    13                 break
    14 if __name__ == "__main__":
    15     HOST, PORT = "localhost", 9999
    16     # Create the server, binding to localhost on port 9999
    17     server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
    18     server.serve_forever()
  • 相关阅读:
    Asp.net2.0页面执行顺序
    [转帖]常用的SQL语句
    [转帖]黑客技术经典问题FAQ
    面试的一些心得
    较全的正则表达式
    很好的创业建议
    [转帖]如何让菜单项与工具栏按钮对应
    源码下载网站
    [转帖]一段测试代码
    GOF设计模式趣解(23种设计模式) <转自百度空间>
  • 原文地址:https://www.cnblogs.com/yunweiqiang/p/6859928.html
Copyright © 2011-2022 走看看