zoukankan      html  css  js  c++  java
  • Python3 Socket和SocketServer 网络编程

    socket只能实现同时一个服务和一个客户端实现交互,socketserver可以实现多个客户端同时和服务端交互

    1.利用Socket编写简单的同一个端口容许多次会话的小案例:

    服务端:

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:CarsonLi
    
    import socket
    '''模拟服务端'''
    server=socket.socket()
    server.bind(('localhost',6969)) #绑定需要监听的端口
    server.listen(5) #开始监听
    print('开始等待客户端发起请求')
    while True:
        conn,addr=server.accept() #等待客户端连接,并且返回两个参数
        #conn是客户端连接过来而在服务器为期生成的一个连接实例, addr为连接的地址
        print('服务器为客户端连接生成的实例:',conn)
        print('客户端连接地址:',addr)
        while True:
            data=conn.recv(1024) #接收客户端发来的信息
            print(data.decode())
            conn.send(data.upper()) #返回个客户端信息
    server.close()
    

      客户端:

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:CarsonLi
    import socket
    '''模拟客户端'''
    client=socket.socket() #声明socket类型,同时创建socket连接对象
    client.connect(('localhost',6969))
    while True:
        msg=input('请输入需要发送的内容>>:').strip()
        if len(msg)==0: #输入信息为空时不发送,否则在linux下运行时会出现死循环
            continue
        else:
            client.send(msg.encode("utf-8")) #发送信息 在python3以后都只能发送byte类型,
            data=client.recv(1024)#接收到的信息,需要定义大小
        print(data.decode())
    
    client.close()
    

      服务端运行结果:

    D:Python3.7.0python.exe D:/PycharmProjects/OldManS14/day07/socket_server.py
    开始等待客户端发起请求
    服务器为客户端连接生成的实例: <socket.socket fd=436, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969), raddr=('127.0.0.1', 64403)>
    客户端连接地址: ('127.0.0.1', 64403)
    第一次
    第二次
    第三次
    第四次
    第五次
    

      客户端运行结果:

    D:Python3.7.0python.exe D:/PycharmProjects/OldManS14/day07/socket_client.py
    请输入需要发送的内容>>:第一次
    第一次
    请输入需要发送的内容>>:第二次
    第二次
    请输入需要发送的内容>>:第三次
    第三次
    请输入需要发送的内容>>:第四次
    第四次
    请输入需要发送的内容>>:第五次
    第五次
    请输入需要发送的内容>>:
    

     2.SocketServer 支持多个客户端

    '''
    SocketServer 支持多个客户端
    '''
    import socketserver
    
    class MyTCPHandler(socketserver.BaseRequestHandler):
        '''
        处理我们的socket,这个类必须继承socketserver.BaseRequestHandler
        并且实现里面的handler函数
        '''
    
        def setup(self):
            print("这里处理请求前的的事情,也可以不写")
            pass
    
        def handle(self):
            '''处理客户端请求'''
            while self:
                try:
                    self.data = self.request.recv(1024).strip()
                    print("{} wrote:".format(self.client_address[0]))#客户端地址
                    print(self.data)
                    self.request.send(self.data.upper())
                except ConnectionResetError as e:
                    print("客户端断开", e)
                    break
    
        def finish(self):
            print("处理请求完成之后的事情,也可以不写")
            pass
    
    if __name__=="__main__":
        HOST,PORT = "localhost",6969
       # server = socketserver.TCPServer((HOST,PORT),MyTCPHandler  #不支持多并发
        server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) #支持多线程,多并发
       # server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)  # 支持多进程,多并发,windows不能实现,linux上可以
        #server.allow_reuse_address() #解决 在 socketServer程序里面出现 地址已经被占用
        server.serve_forever()
    

     3.模拟ftp上传下载(只实现了里面的上传功能,其他功能也大同小异,就没有一一去写)

    import socketserver,os,json
    
    '''模拟ftp上传下载的服务端'''
    
    class MyTCPHandler(socketserver.BaseRequestHandler):
    
        def setup(self):
            pass
    
        def handle(self):
            while True:
                try:
                    self.data = self.request.recv(1024).strip()
                    print("{}".format(self.client_address[0]))
                    msg_dic = json.loads(self.data.decode())
                    print(msg_dic)
                    if hasattr(self,"server_"+msg_dic.get("action")):
                        func = getattr(self,"server_"+msg_dic.get("action"))
                        func(msg_dic)
                except ConnectionResetError as e:
                    print(e)
                    break
    
        def server_put(self,*args):
            '''服务端文件上传操作'''
            msg_dic = args[0]
            file_name = msg_dic.get("file_name") #文件名称
            file_size = msg_dic.get("file_size")#文件大小
            if os.path.isfile(file_name):
                files = file_name.split(".") #截取文件名添加new ,例如 file.txt ==> file_new.txt
                f = open(files[0]+"_new."+files[1],"wb")
            else:
                f = open(file_name, "wb")
            self.request.send(b"200 ok")
            recv_file_size = 0
            while recv_file_size < file_size:
                recv_data = self.request.recv(1024)
                f.write(recv_data)
                recv_file_size += len(recv_data) #大小计算
            else:
                print("file [%s] has uploaded..." % file_name)
                f.close()
    
        def server_get(self,*args):
            ''' 下载文件功能 '''
            pass
    
        def server_del(self,*args):
            ''' 下载删除功能 '''
            pass
    
    if __name__ == "__main__":
        ip,port = "localhost",9999
        server = socketserver.ThreadingTCPServer((ip,port),MyTCPHandler)
        server.serve_forever()
    

      客户端:

    import socket,os,json
    
    '''模拟ftp上传下载的客户端'''
    
    class MyTCPClient(object):
    
        def __init__(self):
            self.client=socket.socket()
    
        def help(self):
            pass
    
        def connection(self,ip,port):
            '''连接服务器'''
            self.client.connect((ip, port))
    
        def interactive(self):
            while True:
                input_str = input(">>:").strip()
                if len(input_str) == 0: continue
                action = input_str.split()[0]
                if hasattr(self,"cmd_"+action): #用反射判断是否存在
                    func = getattr(self,"cmd_"+action)
                    func(input_str)
                else:
                    print(action,"is not exist!")
    
        def client_put(self,*args):
            '''客户端文件上传操作'''
            input_str = args[0]
            input_split = input_str.split()
            if os.path.isfile(input_split[1]):  # 判断是否是文件
                file_size = os.stat(input_split[1]).st_size
                msg_dic = {
                    "action":input_split[0],
                    "file_name":input_split[1],
                    "file_size":file_size
                }
                self.client.send(json.dumps(msg_dic).encode("utf-8"))  #序列化之后编码
                server_respone = self.client.recv(1024)  #等待客户端确认
                f = open(input_split[1],"rb") #打开文件
                for line in f:
                    self.client.send(line)
                else:
                    print(input_split[1],"upload success!")
                    f.close() #关闭文件
            else:
                print(input_split[1], "is not exist!")
    
        def client_get(self,*args):
            '''文件下载操作'''
            pass
    
        def client_del(self,*args):
            '''删除功能'''
            pass
    
    if __name__ == "__main__":
        tcp_client = MyTCPClient()
        tcp_client.connection("localhost",9999)
        tcp_client.interactive()
    

      

  • 相关阅读:
    Smobiler如何实现.net一键开发,ios和android跨平台运行
    使用Smobiler实现类似美团的界面
    疫情当下,企业系统如何快速实现移动化?
    Smobiler针对百度文字识别SDK动态编译与运行
    smobiler自适应不同手机分辨率
    仓库管理移动应用解决方案——C#开发的移动应用开源解决方案
    移动OA办公——Smobiler第一个开源应用解决方案,快来get吧
    react-native 标题随页面滚动显示和隐藏
    react-native 键盘遮挡输入框
    解决adb网络连接中出现的“由于目标计算机积极拒绝,无法连接”错误
  • 原文地址:https://www.cnblogs.com/bert227/p/9786481.html
Copyright © 2011-2022 走看看