Python网络编程学习_Day9

一、socketserver实现多并发

socket只能实现单进程通讯,要实现多进程同时和服务端通讯就要使用socketserver。

代码如下:

1 import socket
2 client = socket.socket()
3 client.connect(("localhost",9000))
4 while True:
5     choice = input(">>>:")
6     if len(choice) == 0:continue
7     client.send(choice.encode())
8     recv = client.recv(1024)
9     print("recved:",recv.decode())
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Liumj
 4 import socketserver
 5 class MyTCPHandler(socketserver.BaseRequestHandler):
 6     def handle(self):
 7         while True:
 8             self.data = self.request.recv(1024).strip()
 9             print(self.client_address[0])
10             print(self.data)
11             self.request.sendall(self.data.upper())
12 if __name__ =="__main__":
13     HOST,PORT = "localhost",9000
14     server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
15     server.serve_forever()

 二、FTP程序开发

1.服务端代码

  1 import socketserver
  2 import configparser
  3 from conf import settings
  4 import os
  5 import hashlib
  6 import time
  7 t = time.strftime("%H_%M_%S")
  8 
  9 STATUS_CODE  = {
 10     250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
 11     251 : "Invalid cmd ",
 12     252 : "Invalid auth data",
 13     253 : "Wrong username or password",
 14     254 : "Passed authentication",
 15     255 : "Filename doesn't provided",
 16     256 : "File doesn't exist on server",
 17     257 : "ready to send file",
 18     258 : "md5 verification",
 19 }
 20 import json
 21 class FTPHandler(socketserver.BaseRequestHandler):
 22     def handle(self):
 23         while True:
 24             self.data = self.request.recv(1024).strip()
 25             print(self.client_address[0])
 26             print(self.data)
 27             if not self.data:
 28                 print("client closed...")
 29                 break
 30             data  = json.loads(self.data.decode())
 31             if data.get('action') is not None:
 32                 print("---->",hasattr(self,"_auth"))
 33                 if hasattr(self,"_%s"%data.get('action')):
 34                     func = getattr(self,"_%s"% data.get('action'))
 35                     func(data)
 36                 else:
 37                     print("invalid cmd")
 38                     self.send_response(251)
 39             else:
 40                 print("invalid cmd format")
 41                 self.send_response(250)
 42 
 43     def send_response(self,status_code,data=None):
 44         '''向客户端返回数据'''
 45         response = {'status_code':status_code,'status_msg':STATUS_CODE[status_code]}
 46         if data:
 47             response.update( data  )
 48         self.request.send(json.dumps(response).encode())
 49 
 50     def _auth(self,*args,**kwargs):
 51         data = args[0]
 52         if data.get("username") is None or data.get("password") is None:
 53             self.send_response(252)
 54 
 55         user =self.authenticate(data.get("username"),data.get("password"))
 56         if user is None:
 57             self.send_response(253)
 58         else:
 59             print("passed authentication",user)
 60             self.user = user
 61             self.send_response(254)
 62     def authenticate(self,username,password):
 63         '''验证用户合法性,合法就返回用户数据'''
 64 
 65         config = configparser.ConfigParser()
 66         config.read(settings.ACCOUNT_FILE)
 67         if username in config.sections():
 68             _password = config[username]["Password"]
 69             if _password == password:
 70                 print("pass auth..",username)
 71                 config[username]["Username"] = username
 72                 return config[username]
 73 
 74     def _put(self,*args,**kwargs):
 75         "client send file to server"
 76         data = args[0]
 77         # if data.get('filename') is None:
 78         #     self.send_response(255)
 79         user_home_dir = "%s/%s" % (settings.USER_HOME, self.user["Username"])
 80         file_abs_path = "%s/%s" % (user_home_dir, data.get('filename'))
 81         print("file abs path", file_abs_path)
 82         print("server.....")
 83         self.send_response(257)
 84         received_size = 0
 85         total_size = int(self.request.recv(1024))
 86         file_obj = open(file_abs_path+t, "wb")
 87         #print("zhaodao.....")
 88         while received_size < total_size:
 89             data = self.request.recv(4096)
 90             received_size +=len(data)
 91             file_obj.write(data)
 92         else:
 93             print("---recv done...")
 94             file_obj.close()
 95 
 96     def _get(self,*args,**kwargs):
 97         data = args[0]
 98         if data.get('filename') is None:
 99             self.send_response(255)
100         user_home_dir = "%s/%s" %(settings.USER_HOME,self.user["Username"])
101         file_abs_path = "%s/%s" %(user_home_dir,data.get('filename'))
102         print("file abs path",file_abs_path)
103 
104         if os.path.isfile(file_abs_path):
105             file_obj = open(file_abs_path,"rb")
106             file_size = os.path.getsize(file_abs_path)
107             self.send_response(257,data={'file_size':file_size})
108             self.request.recv(1) #等待客户端确认
109 
110             if data.get('md5'):
111                 md5_obj = hashlib.md5()
112                 for line in file_obj:
113                     self.request.send(line)
114                     md5_obj.update(line)
115                 else:
116                     file_obj.close()
117                     md5_val = md5_obj.hexdigest()
118                     self.send_response(258,{'md5':md5_val})
119                     print("send file done....")
120             else:
121                 for line in file_obj:
122                     self.request.send(line)
123                 else:
124                     file_obj.close()
125                     print("send file done....")
126         else:
127             self.send_response(256)
128 
129     def _ls(self,*args,**kwargs):
130         pass
131 
132     def _cd(self, *args, **kwargs):
133         pass
134 
135 if __name__ == "__main__":
136     HOST, PORT = "localhost", 9000
ftp_server

2.客户端代码

  1 import socket
  2 import os ,json
  3 import optparse
  4 import getpass
  5 import hashlib
  6 import sys 
  7 
  8 STATUS_CODE  = {
  9     250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
 10     251 : "Invalid cmd ",
 11     252 : "Invalid auth data",
 12     253 : "Wrong username or password",
 13     254 : "Passed authentication",
 14     255 : "Filename doesn't provided",
 15 }
 16 
 17 class FTPClient(object):
 18     def __init__(self):
 19         parser = optparse.OptionParser()
 20         parser.add_option("-s","--server", dest="server", help="ftp server ip_addr")
 21         parser.add_option("-P","--port",type="int", dest="port", help="ftp server port")
 22         parser.add_option("-u","--username", dest="username", help="username")
 23         parser.add_option("-p","--password", dest="password", help="password")
 24         self.options , self.args = parser.parse_args()
 25         self.verify_args(self.options,self.args)
 26         self.make_connection()
 27 
 28     def make_connection(self):
 29         self.sock = socket.socket()
 30         self.sock.connect((self.options.server,self.options.port))
 31 
 32     def verify_args(self, options,args):
 33         '''校验参数合法型'''
 34         if options.username is not None and options.password is not  None:
 35             pass
 36         elif options.username is None and options.password is None:
 37             pass
 38         else:
 39             #options.username is None or options.password is None:
 40             exit("Err: username and password must be provided together..")
 41 
 42         if options.server and options.port:
 43             #print(options)
 44             if options.port >0 and options.port <65535:
 45                 return True
 46             else:
 47                 exit("Err:host port must in 0-65535")
 48 
 49     def authenticate(self):
 50         '''用户验证'''
 51         if self.options.username:
 52             print(self.options.username,self.options.password)
 53             return  self.get_auth_result(self.options.username, self.options.password)
 54         else:
 55             retry_count = 0
 56             while retry_count <3:
 57                 username = input("username:").strip()
 58                 password = input("password:").strip()
 59                 return self.get_auth_result(username,password)
 60 
 61     def get_auth_result(self,user,password):
 62         data = {'action':'auth',
 63                 'username':user,
 64                 'password':password}
 65 
 66         self.sock.send(json.dumps(data).encode())
 67         response = self.get_response()
 68         if response.get('status_code') == 254:
 69             print("Passed authentication!")
 70             self.user = user
 71             return True
 72         else:
 73             print(response.get("status_msg"))
 74 
 75     def get_response(self):
 76         '''得到服务器端回复结果'''
 77         data = self.sock.recv(1024)
 78         print("server res", data)
 79         data = json.loads(data.decode())
 80         return data
 81 
 82 
 83 
 84     def interactive(self):
 85         if self.authenticate():
 86             print("---start interactive iwth u...")
 87             while True:
 88                 choice = input("[%s]:"%self.user).strip()
 89                 if len(choice) == 0:continue
 90                 cmd_list = choice.split()
 91                 if hasattr(self,"_%s"%cmd_list[0]):
 92                     func = getattr(self,"_%s"%cmd_list[0])
 93                     func(cmd_list)
 94                 else:
 95                     print("Invalid cmd.")
 96     
 97     def __md5_required(self,cmd_list):
 98         '''检测命令是否需要进行MD5验证'''
 99         if '--md5' in cmd_list:
100             return True
101     def show_progress(self,total):
102         received_size = 0 
103         current_percent = 0 
104         while received_size < total:
105              if int((received_size / total) * 100 )   > current_percent :
106                   print("#",end="",flush=True)
107                   current_percent = int((received_size / total) * 100 )
108              new_size = yield 
109              received_size += new_size
110     def _get(self,cmd_list):
111         print("get--",cmd_list)
112         if len(cmd_list) == 1:
113             print("no filename follows...")
114             return
115         data_header = {
116             'action':'get',
117             'filename':cmd_list[1]
118         }
119         if self.__md5_required(cmd_list):
120             data_header['md5'] = True
121 
122         self.sock.send(json.dumps(data_header).encode())
123         response = self.get_response()
124         print(response)
125         if response["status_code"] ==257:#ready to receive
126             self.sock.send(b'1')#send confirmation to server 
127             base_filename = cmd_list[1].split('/')[-1]
128             received_size = 0
129             file_obj = open(base_filename,"wb")
130             if self.__md5_required(cmd_list):
131                 md5_obj = hashlib.md5()
132                 progress = self.show_progress(response['file_size']) #generator 
133                 progress.__next__()
134                 while received_size < response['file_size']:
135                     data = self.sock.recv(4096)
136                     received_size += len(data)
137                     try:
138                       progress.send(len(data))
139                     except StopIteration as e:
140                       print("100%")
141                     file_obj.write(data)
142                     md5_obj.update(data)
143                 else:
144                     print("----->file rece done----")
145                     file_obj.close()
146                     md5_val = md5_obj.hexdigest()
147                     md5_from_server = self.get_response()
148                     if md5_from_server['status_code'] == 258:
149                         if md5_from_server['md5'] == md5_val:
150                             print("%s 文件一致性校验成功!" % base_filename)
151                     #print(md5_val,md5_from_server)
152 
153             else:
154                 progress = self.show_progress(response['file_size']) #generator 
155                 progress.__next__()
156 
157                 while received_size < response['file_size']:
158                     data = self.sock.recv(4096)
159                     received_size += len(data)
160                     file_obj.write(data)
161                     try:
162                       progress.send(len(data))
163                     except StopIteration as e:
164                       print("100%")
165 
166                 else:
167                     print("----->file recv done----")
168                     file_obj.close()
169     def _put(self,cmd_list):
170         print("put----",cmd_list)
171         if len(cmd_list) == 1:
172             print("no filename follows...")
173             return
174         data_header = {
175             'action':'put',
176             'filename':cmd_list[1]
177         }
178         self.sock.send(json.dumps(data_header).encode())
179         #response = self.get_response()
180         #print(response)
181         print("client......")
182         file_obj = open(cmd_list[1],"rb")
183         file_size = os.stat(cmd_list[1]).st_size
184         print(file_size)
185         self.sock.send(str(file_size).encode())
186         self.sock.recv(1024) #等待服务端确认
187         progress = self.show_progress(file_size)  # generator
188         progress.__next__()
189         for i in file_obj:
190             self.sock.send(i)
191         else:
192             try:
193                 progress.send(int(file_size))
194             except StopIteration as e:
195                 print("100%")
196             file_obj.close()
197             print("send done...")
198 if __name__ == "__main__":
199     ftp = FTPClient()
200     ftp.interactive() #交互
ftp_client
原文地址:https://www.cnblogs.com/liumj0305/p/6134956.html