python——网络编程

来源:互联网 发布:windows jenkins shell 编辑:程序博客网 时间:2024/05/21 14:00

网络通信示意图

这里写图片描述

socket编程网络步骤图

这里写图片描述

客户端

import socketclient=socket.socket()#声明socket类型,同时生成socket连接对象client.connect(("localhost",6969))#连接地址(IP地址和端口)client.send(b"hello world")#python3只能发byte字节类型data=client.recv(1024)print("recv:",data)client.close()

服务端

import  socketserver=socket.socket()#声明类型,使用的是默认类型server.bind(("localhost",6969))#绑定要监听的端口server.listen()#监听print("我要开始等电话了")#conn就是客户端连过来而在服务器端为其生成的一个连接实例conn,addr=server.accept()#等电话打进来,conn就是客户端连过来而在服务器端为其生成的一个连接实例,addr链接的地址print(conn,addr)             #('127.0.0.1', 3020)是地址print("电话来了")data=conn.recv(1024)print("recv:",data)conn.send(data.upper())#发送给客户端server.close()

能连续发送命令给服务端,服务端给客户端返回执行的命令结果

服务端代码

import socketimport osimport timeserver=socket.socket()server.bind(("localhost",9999))server.listen()while True:    coon,addr=server.accept()    print("new conn:",addr)    while True:        print("等待新指令")        data=coon.recv(1024)        if not data:            print("客户端已断开")            break        print("执行指令:",data.decode())        cmd_res=os.popen(data.decode()).read()#接受字符串,执行结果也是字符串        print("before send",len(cmd_res))        if len(cmd_res)==0:            cmd_res="cmd has no output"        '''        下面发送的两个包在一起,就有可能出现粘包的现象,因为缓冲区会把这两条语句当做一条语句发送        '''        coon.send(str(len(cmd_res.encode())).encode("utf-8"))#先发大小给客户端        #time.sleep(0.5)#这样也能解决粘包的问题,但是会产生延时,不适合实时通信的        client_ack=coon.recv(1024)#等待客户端确认,这样就不会粘包了        print("ack from client:",client_ack.decode())        coon.send(cmd_res.encode("utf-8"))        print("send done")server.close()

客户端

import socketclient=socket.socket()client.connect(("localhost",9999))while True:    cmd=input(">>:").strip()    if len(cmd)==0: continue    client.send(cmd.encode("utf-8"))    cmd_res_size=client.recv(1024)#接受命令结果的长度    print("命令结果的大小:",cmd_res_size)    client.send("可以开始接收了".encode("utf-8"))    received_size=0    received_data=b""    while received_size<int(cmd_res_size.decode()):        data=client.recv(1024)        received_size+=len(data)#每次收到的可能小于1024(recv(1024)这个只是说每次最大能接受1024,而不是每次就接受1024,这个值一般最大为8792),所以必须用len判断        print(data.decode())        received_data+=data    else:        print("cmd res receive done...",received_size)        print(received_data.decode())client.close()

单用户使用get下载文件,并能验证md5值

下载文件步骤

这里写图片描述

服务端代码

import socketimport osimport hashlibimport timeserver=socket.socket()server.bind(("localhost",9999))server.listen()while True:    coon,addr=server.accept()    print("new conn:",addr)    while True:        print("等待新指令")        data=coon.recv(1024)        if not data:            print("客户端已断开")            break        cmd,filename=data.decode().split()        print(filename)        if os.path.isfile(filename):#判断是否为文件            f=open(filename,"rb")            m=hashlib.md5()            file_size=os.stat(filename).st_size#获取文件的大小            coon.send(str(file_size).encode())#发送文件长度            coon.recv(1024)#等待确认            for line in f:                m.update(line)                coon.send(line)            print("file md5",m.hexdigest())            f.close()            coon.send(m.hexdigest().encode())#给客户端发送md5值        print("send done")server.close()

客户端代码

import socketimport hashlibclient=socket.socket()client.connect(("localhost",9999))while True:    cmd=input(">>:").strip()    if len(cmd)==0: continue    if cmd.startswith("get"):        client.send(cmd.encode())        server_response=client.recv(1024)        print("server response:",server_response)        client.send(b"ready to recv file")        file_total_size=int(server_response.decode())        received_size=0        filename=cmd.split()[1]        f=open(filename+".new","wb")        m=hashlib.md5()        while received_size<file_total_size:            '''            通过下面的这个对size的控制可以防止位置1和位置2处发生粘包的发生,因为在接收文件最后不足1024的时候剩多少,我收多少            (粘包发生的原因就是文件收到最后不足1024的时候,可能将md5和文件不足1024的部分一起接收了,但是也有可能不发生粘包,因为每次发送接收的不一定就是1024)            '''            if file_total_size-received_size>1024:#要收不止一次                size=1024            else:                size=file_total_size-received_size            data=client.recv(size)#位置1            received_size+=len(data)            m.update(data)            f.write(data)            print(file_total_size,received_size)        else:            new_file_md5=m.hexdigest()            print("file recv done")            f.close()        server_file_md5=client.recv(1024)#位置2        print("server file md5:",server_file_md5)        print("client file md5:",new_file_md5)client.close()

* 支持多用户同时上传下载(并发)——socketServer,简例*

创建一个sockerServer的步骤

这里写图片描述

服务端

import socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):    def handle(self):        while True:            try:                self.data=self.request.recv(1024).strip()                print("{} wrote".format(self.client_address[0]))                print(self.data)                # if not self.data:#客户端断了                #     print(self.client_address,"断开了")                #     break                self.request.send(self.data.upper())            except ConnectionResetError as e:                print("err",e)                breakif __name__== "__main__":    HOST,PORT="localhost",9999    #创建服务端,绑定主机端口9999    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)#多线程并发    #server=socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler)#多进程并发,在windows上不好使,在Linux上可以,因为windows上的进程不能通过fork实现    server.serve_forever()

客户端

import socketclient=socket.socket()#声明socket类型,同时生成socket连接对象client.connect(("localhost",9999))#连接地址(IP地址和端口)while True:    msg=input(">>:").strip()    client.send(msg.encode("utf-8"))#python3只能发byte字节类型    data=client.recv(1024)    print("recv:",data.decode())client.close()

简易版的ftp并发上传

客户端代码

import socketimport osimport jsonclient=socket.socket()client.connect(("localhost",9999))class FtpClient(object):    def __init__(self):        self.client=socket.socket()    def help(self):        msg='''        ls        pwd        cd ../..        get filename        put filename        '''        print(msg)    def connect(self,ip,port):        self.client.connect((ip,port))    def interactive(self):        #self.authenticate()        while True:            cmd=input(">>").strip()            if len(cmd)==0: continue            cmd_str=cmd.split()[0]            if hasattr(self,"cmd_%s"%cmd_str):#反射                func=getattr(self,"cmd_%s"%cmd_str)                func(cmd)            else:                self.help()    def cmd_put(self,*args):        cmd_split=args[0].split()        if len(cmd_split)>1:            filename=cmd_split[1]            if os.path.isfile(filename):                filesize=os.stat(filename).st_size                msg_dic={                    "action":"put",                    "filename":filename,                    "size":filesize,                    "overridden":True                }                self.client.send(json.dumps(msg_dic).encode("utf-8"))                print("send",json.dumps(msg_dic).encode("utf-8"))                #防止粘包,等服务器确认                server_response=self.client.recv(1024)                f=open(filename,"rb")                for line in f:                    self.client.send(line)                else:                    print("file upload success...")                    f.close()            else:                print(filename,"is not exist")    def cmd_get(self):        passftp=FtpClient()ftp.connect("localhost",9999)ftp.interactive()

服务端代码

import socketserverimport jsonimport osclass MyTCPHandler(socketserver.BaseRequestHandler):#括号里面的是固定的    def put(self,*args):        '''接收客户端文件'''        cmd_dic=args[0]        filename=cmd_dic["filename"]        filesize=cmd_dic["size"]        if os.path.isfile(filename):            f=open(filename+".new","wb")        else:            f=open(filename,"wb")        self.request.send(b"200 ok")        received_size=0        while received_size<filesize:            data=self.request.recv(1024)            f.write(data)            received_size+=len(data)        else:            print("file [%s] has uploaded..."%filename)    def handle(self):#这里面的才是跟客户端交互的        while True:            try:                self.data=self.request.recv(1024).strip()                print("{} wrote".format(self.client_address[0]))                print(self.data)                cmd_dic=json.loads(self.data.decode())                action=cmd_dic["action"]                if hasattr(self,action):#判断是否有action所对应的字符串的函数                    func=getattr(self,action)#获取action对应的函数                    func(cmd_dic)#执行其对应的函数            except ConnectionResetError as e:#捕获异常的                print("err",e)                break'''下面是固定的写法'''if __name__== "__main__":    HOST,PORT="localhost",9999    #创建服务端,绑定主机端口9999    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)    server.serve_forever()
原创粉丝点击