python学习第八天

动态导入模块

import os,sys

base =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(base)

 

'''解释器内部导入方式,只导入module a'''

# mod =__import__("a.test")

# obj =mod.test.m()

# print(mod.test.m().name)

 

'''官方建议用法,直接导入module a.test'''

import importlib

test =importlib.import_module("a.test")

# print(test.m().name)

 

断言

'''断言aa的数据类型是字符串,断言正确则执行后面的程序,错误则报错,程序停止'''
assert type("aa") is str
print("ddd")

 

socket参数

socket.socket(family=AF_INETtype=SOCK_STREAMproto=0fileno=None)  必会

socket.getaddrinfo(hostportfamily=0type=0proto=0flags=0) #获取要连接的对端主机地址 必会

sk.bind(address) 必会  s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。

sk.listen(backlog) 必会  开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5这个值不能无限大,因为要在内核中维护连接队列

sk.setblocking(bool) 必会  是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

sk.accept() 必会  接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来

sk.connect(address) 必会 连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

sk.connect_ex(address) 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

sk.close() 必会 关闭套接字

sk.recv(bufsize[,flag]) 必会 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag]) 与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

sk.send(string[,flag]) 必会 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

sk.sendall(string[,flag]) 必会 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过递归调用send,将所有内容发送出去。

sk.sendto(string[,flag],address) 将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

sk.settimeout(timeout) 必会 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

sk.getpeername()  必会 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

 

socket实现简易ssh

服务器端

import socket,os

server =socket.socket()

server.bind(("localhost",9999))

 

server.listen()

 

while True:

    conn,addr =server.accept()

    print("新的连接:",addr)

    while True:

        print("等待新指令")

        cmd =conn.recv(1024)

        if len(cmd) ==0:

            print("客户端断开连接")

            break

        print("执行指令%s"%cmd)

        cmd_res =os.popen(cmd.decode()).read()

        res_size =len(cmd_res)

        if res_size ==0:

            cmd_res ="指令没有执行"

        '''发送指令结果长度,方便客户端判断需要接收多少数据'''

        conn.send(str(res_size).encode("utf-8"))

        '''等待客户端返回确认信息,否则不发送指令执行结果,防止粘包'''

        client_ack =conn.recv(1024)

        conn.send(cmd_res.encode("utf-8"))

        print("指令执行完毕")

server.close()

 

客户端

import socket

client =socket.socket()

client.connect(("localhost",9999))

 

while True:

    cmd =input(">>>:").strip().encode()

    if len(cmd) ==0:continue

    client.send(cmd)

    '''确认指令结果长度'''

    data_size =client.recv(1024)

    '''发送确认信息给服务端,以便开始接收指令结果'''

    server_ack =client.send(b"ok")

    res_size =0

    res_data =b''

    '''只要接收的数据长度跟之前确认的数据长度不一致就继续接收数据'''

    while res_size != int(data_size.decode()):

        data =client.recv(1024)

        res_size +=len(data)

        res_data +=data

    else:

        print("指令执行结果接收完毕")

        print(res_data.decode())

 

client.close()

 

socket实现ftp

服务器端

import socket,os,hashlib

server =socket.socket()

server.bind(("localhost",9999))

 

server.listen()

 

while True:

    conn,addr =server.accept()

    print("新的连接:",addr)

    while True:

        print("等待新指令")

        cmd =conn.recv(1024)

        if len(cmd) ==0:

            print("客户端断开连接")

            break

        print("执行指令%s"%cmd)

        '''获取指令中的文件名'''

        filename =os.path.basename(cmd)

        '''判断指定的文件是否存在'''

        if os.path.isfile(filename):

            m =hashlib.md5()

            '''获取文件属性中的文件大小'''

            file_size =os.stat(filename).st_size

            conn.send(str(file_size).encode())

            client_ack =conn.recv(1024)

            with open(filename,"rb") as f:

                for line in f:

                    '''对文件内容进行md5加密'''

                    m.update(line)

                    conn.send(line)

                    '''输出md5值'''

                print(m.hexdigest())

            conn.send(m.hexdigest().encode())

        else:

            print("文件不存在")

        print("发送完毕")

server.close()

 

客户端

import socket,hashlib,os

client =socket.socket()

client.connect(("localhost",9999))

while True:

    cmd =input(">>:").strip()

    if len(cmd) ==0:continue

    filename =os.path.basename(cmd)

    '''判断输入的指令是不是以get开头'''

    if cmd.startswith("get"):

        client.send(cmd.encode("utf-8"))

    data_size =client.recv(1024)

    client.send(b'ok')

    receive_size =0

 

    m =hashlib.md5()

    while receive_size !=int(data_size.decode()):

        '''判断未接收文件大小,大于1024则设定size为1024,否则size设定为剩余未接收的文件的大小。避免md5与文件内容粘包'''

        if int(data_size.decode()) -receive_size >1024:

            size =1024

        else:

            size =int(data_size.decode()) -receive_size

        with open(filename +".new","wb") as f:

            data =client.recv(size)

            receive_size +=len(data)

            m.update(data)

            f.write(data)

    else:

        new_filemd5 =m.hexdigest()

        print("文件接收完毕")

        server_md5 =client.recv(1024)

    print("client md5",new_filemd5)

    print("server md5",server_md5)

client.close()

 

socket server模块

import socketserver

'''定义请求处理类,继承BaseRequestHandler,重构它的handle方法'''

class MyTCPHander(socketserver.BaseRequestHandler):

    def handle(self):

        while True:

            try:

                self.data =self.request.recv(1024).strip()

                if not self.data:

                    break

                print("{}wrote:".format(self.client_address[0]))

                print(self.data)

                self.request.sendall(self.data.upper())

            except ConnectionResetError as e:

                print("err",e)

                break

 

if __name__ =="__main__":

    HOST,PORT ="localhost",9999

    '''实例化一种server类,除了TCPServer还可以定义UDPServer,将监听的IP和端口及请求处理类传入'''

    server =socketserver.TCPServer((HOST,PORT),MyTCPHander)

    '''调用server对象的serve_forever()方法去处理多个请求'''

    server.serve_forever()

 

创建一个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.   定义一个请求处理类,继承BaseRequestHandler,重构它的handle() 方法,handle() 处理请求的所有交互
  2. Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.实例化一种server类,比如ThreadingTCPServer,将监听的IP和端口以及请求处理类传给它
  3. Then call the handle_request() orserve_forever() method of the server object to process one or many requests.调用server对象的serve_forever()方法去处理多个请求
  4. Finally, call server_close() to close the socket.调用server_close()关闭服务器程序

 

posted @ 2017-03-25 18:52  魅力宁波  阅读(147)  评论(0)    收藏  举报