美文网首页
python之socket编程

python之socket编程

作者: ivan_cq | 来源:发表于2019-02-18 01:13 被阅读0次

    • 实例一:最简单的socket例子
      这个程序,实现了客户端向服务端发送数据,服务端将小写字母变为大写并且返回
    服务端
    import socket
    server=socket.socket()              #默认ipv4 tcp/ip 相当于声明socket类型同时生成socket连接对象  既定义了地址簇,又定义了协议类型
    server.bind(('localhost',1010) )        #绑定要监听的端口,只接受一个参数,是一个元组
    
    server.listen()                         #开始监听
    print('我要开始等电话了!')             #但是这个地方还没有真正开始等,只是做好了准备工作
    
    
    
    conn,addr=server.accept()               #等电话打进来,真正的开始等电话打进来
    print(conn,addr)                        #conn就是客户端连过来而在服务器端为其生成的一个连接实例,也就是标记,后面就是对方的地址
    print("电话来了!")
    data=conn.recv(1024)                    #使用实例接受,发送
    print(data)
    conn.send(data.upper())                 #发过去变成大写
    server.close()                          #关闭手机 所以是server
    
    
    
    # server.accept()
    # data=server.recv(1024)
    # print('recv ',data)
    # server.send(data.upper())
    # server.close()
    #TypeError: a bytes-like object is required, not 'str'
    #不能直接使用server去接听 server.accept
    #这里就需要想手机切换通话,只是一根电话线,让别的人通过这一根电话线打进来切换接听另一个人
    #所以用该给每个人标记一下  conn,addr=server.accept()    返回第一个是连接的标记位,第二个是对方的地址
    
    
    结果:
    F:\anaconda\python.exe F:/web/s14/网络编程、socket编程/socket_server.py
    我要开始等电话了!
    <socket.socket fd=272, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 1010), raddr=('127.0.0.1', 49866)> ('127.0.0.1', 49866)
    电话来了!
    b'hello world!'
    
    客户端
    
    import socket
    client=socket.socket()                           #默认ipv4 tcp/ip 相当于声明socket类型同时生成socket连接对象
    client.connect(('localhost',1010))
    client.send(b"hello world!")         #  不加b会出现这个错误   : TypeError: a bytes-like object is required, not 'str'   在python2里面可以发字符串、字节bytes
    #但是在python里只能发比特流的bytes类型
    data=client.recv(1024)                           #收1024字节的数据   1kb
    print(data)
    client.close()
    
    结果:
    
    F:\anaconda\python.exe F:/web/s14/网络编程、socket编程/socket_client.py
    b'HELLO WORLD!'
    
    
    • 实例二:实现服务器和客户端重复发送和接受多次
    客户端
    import socket
    client=socket.socket()
    client.connect(('localhost',1010))
    while True:
        msg=input('>>:').strip()
        if len(msg) == 0:continue
        client.send(msg.encode("utf-8"))
        data=client.recv(1024)
        print(data.decode())
    
    client.close()
    
    
    
    
    服务端
    import socket
    server=socket.socket()
    server.bind(('localhost',1010) )
    server.listen(5)
    while True:    #如果没有这个while循环那么一旦客户端关闭连接,在linux、mac系统上,服务端一直收的都是空,陷入一个死循环。而在windows上就会报错。
        conn,addr=server.accept()               #必须放在外面,如果放在里面,可以同时接两个电话,但是只能说一句
        while True:
            data=conn.recv(1024)
            if not data:
                print("client lost!")
                break
            print(data.decode())
            conn.send(data.upper())
    
    server.close()
    
    
    • 实例三:socket实现简单ssh功能(处理大数据)
    客户端
    import socket
    client=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)
        recv_data = b''
        recv_size = 0
        while recv_size < int(cmd_res_size.decode()):
            data=client.recv(1024)
            recv_size += len(data)      #每次收到的结果很可能小于1024 所以这里必须用len判断
            print(recv_size)
            recv_data+=data
        else:
            print("cmd res recive done!",recv_size)
            print(recv_data.decode())
    
    
    client.close()
    
    服务端
    import socket
    import os
    server=socket.socket()
    server.bind(('localhost',9999))
    server.listen()
    
    while True:
        conn,addr=server.accept()
        while  True:
            print("等待新指令")
            data=conn.recv(1024)
            if not data:
                print("客户端已断开!")
                break
            print("执行指令:",data)
            cmd_res=os.popen(data.decode()).read()      #接受字符串,执行结果也是字符串
    
            if len(cmd_res) == 0:
                cmd_res='cmd has no output!'
            #conn.send(str(len(cmd_res)).encode('utf-8'))
            conn.send(str(len(cmd_res.encode())).encode("utf-8")) # 整数不能直接encode得先str      先把大小发给客户端
            conn.send(cmd_res.encode('utf-8'))
    
    server.close()
    
    
    • 实例四:利用socket实现文件传输
    服务端
    import socket
    import os,hashlib
    server=socket.socket()
    server.bind(('localhost',9999))
    server.listen()
    
    while True:
        conn,addr=server.accept()
        while  True:
            print("等待新指令")
            data=conn.recv(1024)
            if not data:
                print("客户端已断开!")
                break
            cmd,filename=data.decode().split()
            if os.path.isfile(filename):
                f=open(filename,'rb')
                m=hashlib.md5()
                file_size=os.stat(filename).st_size
                conn.send(str(file_size).encode('utf-8'))   #发送文件大小
                conn.recv(1024)         #wait for ack
                for line in f:
                    m.update(line)
                    conn.send(line)
                f.close()
                conn.send(m.hexdigest().encode())       #send md5
                print(m.hexdigest())
            print('send done!')
    
    server.close()
    
    客户端
    import socket,hashlib
    client=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)
            client.send("ready to recv file".encode())      #ack
            file_total_size = int(server_response.decode())
            rece_size=0
            filename=cmd.split()[1]
            f=open(filename + '.new',"wb")
            m=hashlib.md5()
            while rece_size < file_total_size:  #解决了粘包,有可能大于,就把MD5粘过来了
                if file_total_size-rece_size>1024:  #代表要收不止一次
                    size=1024
                else:                               #最后一次,剩多少,收多少
                    size=file_total_size-rece_size
                data=client.recv(size)
                rece_size +=len(data)
                m.update(data)
                f.write(data)
            else:
                new_file_md5=m.hexdigest()
                print(rece_size,file_total_size)
                f.close()
            server_file_md5 = client.recv(1024)
            print("server file md5", server_file_md5.decode())
            print("client file md5", new_file_md5)
    client.close()
    
    
    md5校验
    import hashlib
    m=hashlib.md5()
    m.update(b"test")
    m.update(b'abc')
    print(m.hexdigest())
    m2=hashlib.md5()
    m2.update(b'testabc')
    print(m2.hexdigest())
    #证明了逐行 md5 和一起md5的效果是一样的
    
    • 实例五:通过socketserver实现并发处理
    服务端
    import socketserver
    class MyTCPHandler(socketserver.BaseRequestHandler):
        def handle(self):       #默认在父类里是空的,客户端所有的交互都是在handle里完成的
            while True:
                try:
                    self.data=self.request.recv(1024).strip()           #ConnectionResetError
                    print("{} wrote: ".format(self.client_address[0]))  #打印客户端的ip地址
                    print(self.data)
                    # if not self.data:           #代表客户端断开
                    #     print(self.client_address,"断开了")
                    #     break                     #在使用socket时候,windows上关闭客户端会报错,linux'会陷入无限循环而不报错
                                                    #所以 需判断
                                                    #而在socketserver上widows和linnux上断开客户端都会报ConnectionResetError
                                                    #所以使用异常处理
                    self.request.send(self.data.upper())
                except ConnectionResetError as e:
                    print("err",e)
                    break
    
    #每一个客户端的请求过来都会实例化我们新创建的类
    if __name__ == '__main__':
        HOST,PORT = 'localhost', 6969
        # server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
        server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)  #多并发
        server.serve_forever()
    

    项目:实现ftp服务

    相关文章

      网友评论

          本文标题:python之socket编程

          本文链接:https://www.haomeiwen.com/subject/mycweqtx.html