FTP jobs: uploading and downloading files
Service Side
Import socketimport structimport jsonimport subprocessimport osclass mytcpserver:address_family = Socket.AF_INET So Cket_type = socket. Sock_stream allow_reuse_address = False max_packet_size = 8192 coding= ' utf-8 ' request_queue_size = 5 server _dir= ' File_upload ' def __init__ (self, server_address, bind_and_activate=true): "" "Constructor. May is extended, do not override. "" " Self.server_address=server_address Self.socket = Socket.socket (self.address_family, Self.socket_type) if Bind_and_activate:try:self.server_bind () Self.s Erver_activate () Except:self.server_close () Raise Def server_bind (self): "" "called by constructor to bind the socket. "" "If self.allow_reuse_address:self.socket.setsockopt (socket. Sol_socket, SOCKET. SO_REUSEADDR, 1) self.socket.bind (self.server_address) Self.server_address = Self.socket.getsockname () def server_activate (self): "" "called by constructor to Activa Te the server. "" "Self.socket.listen (self.request_queue_size) def server_close (self):" "" Called to clean-up the server. "" "Self.socket.close () def get_request (self):" "" Get the request and client address from the SOC Ket. "" "Return Self.socket.accept () def close_request (self, request):" "called Uest. "" " Request.close () def run (self): while True:self.conn,self.client_addr=self.get_request () p Rint (' From client ', self.client_addr) while True:try:head_struct = Self.con N.RECV (4) if not head_struct:break Head_len = struct.unpack (' i ', head_struct) [0] Head_json = Self.conn.recv (Head_len). Decode (self.coding) head_dic = Json.loads (head_json) print (head_dic) #head_dic ={' cmd ': ' Put ', ' filename ': ' A.tx T ', ' filesize ': 123123} cmd=head_dic[' cmd ' if Hasattr (self,cmd): Func=getattr (Self,cmd) func (head_dic) except Exception:break def put (Self,args): File_path=os.path.normpath (Os.path.join (Self.server_dir, args[' Filena Me ']) filesize=args[' filesize ' recv_size=0 print ('-----> ', File_path) with open (fi Le_path, ' WB ') as F:while recv_size < Filesize:recv_data=self.conn.recv (self.max_packet_size ) F.write (Recv_data) Recv_size+=len (recv_data) print (' recvsize:%s filesize:%s '% (recv_size,filesize)) Tcpserver1=mytcpserver ((' 127.0.0.1 ', 8080)) Tcpserver1.run () #下列代码与本题无关class myudpserver: "" " UDP server class. "" " Address_family = socket.af_inet Socket_type = socket. Sock_dgram allow_reuse_address = False max_packet_size = 8192 coding= ' utf-8 ' def get_request (self): dat A, client_addr = Self.socket.recvfrom (self.max_packet_size) return (data, Self.socket), Client_addr def server_a Ctivate (self): # need-to-call listen () for UDP. Pass Def shutdown_request (self, request): # need to shutdown anything. Self.close_request (Request) def close_request (self, request): # need to close anything. Pass
Client
Import socketimport structimport jsonimport osclass mytcpclient:address_family = socket.af_inet Socket_type = Socke T.sock_stream allow_reuse_address = False max_packet_size = 8192 coding= ' utf-8 ' request_queue_size = 5 def __init__ (self, server_address, connect=true): self.server_address=server_address self.socket = Socket.socket (self.address_family, Self.socket_type) if Connect:try: Self.client_connect () Except:self.client_close () Raise Def client_connect ( Self): Self.socket.connect (self.server_address) def client_close (self): Self.socket.close () def run (SE LF): While True:inp=input (">>:"). Strip () if not inp:continue l=inp.split () Cmd=l[0] If Hasattr (self,cmd): Func=getattr (Self,cmd) func (l) def Put (Self,args): CMd=args[0] filename=args[1] if not os.path.isfile (filename): print (' file:%s are NOT exists '%filen AME) return else:filesize=os.path.getsize (filename) head_dic={' cmd ': cmd, ' filename ': OS . Path.basename (filename), ' filesize ': filesize} print (Head_dic) head_json=json.dumps (head_dic) head_jso N_bytes=bytes (head_json,encoding=self.coding) head_struct=struct.pack (' I ', Len (head_json_bytes)) Self.socket. Send (Head_struct) self.socket.send (head_json_bytes) send_size=0 with open (filename, ' RB ') as F: For line F:self.socket.send (line) Send_size+=len (line) print (Send_si Ze) else:print (' upload successful ') client=mytcpclient ((' 127.0.0.1 ', 8080)) Client.run ()
Link legitimacy for a certified client
If you want to implement a simple client link authentication function in a distributed system, and not as complex as SSL, then use hmac+ to add salt to achieve
Service Side
#_ *_coding:utf-8_*___author__ = ' Linhaifeng ' from socket import *import hmac,ossecret_key=b ' Linhaifeng Bang Bang Bang ' DEF Conn_auth (conn): "Authenticated client link:P Aram Conn:: Return: ' ' Print (' start verifying the legitimacy of new links ') Msg=os.urandom (32) Conn.sendall (msg) h=hmac.new (secret_key,msg) digest=h.digest () Respone=conn.recv (Len (Digest)) return hmac.com Pare_digest (respone,digest) def data_handler (conn,bufsize=1024): If not Conn_auth (conn): Print (' The link is illegal, off ') Conn.close () return print (' link valid, start communication ') while TRUE:DATA=CONN.RECV (bufsize) if not data:break Conn.sendall (Data.upper ()) def Server_handler (ip_port,bufsize,backlog=5): "Handles only links:p Aram Ip_port:: RET urn: "' Tcp_socket_server=socket (af_inet,sock_stream) tcp_socket_server.bind (ip_port) tcp_socket_server.liste N (backlog) while true:conn,addr=tcp_socket_server.accept () print (' New connection [%s:%s] '% (addr[0],addr[1]) Data_handler (conn,bufsize) if __name__ = = ' __main__ ': ip_port= (' 127.0.0.1 ', 9999) bufsize=1024 Server_handler (ip_port,bufsize)
Client (legal)
#_ *_coding:utf-8_*___author__ = ' Linhaifeng ' from socket import *import hmac,ossecret_key=b ' Linhaifeng Bang Bang Bang ' DEF Conn_auth (conn): " Verify client-to-server link :p Aram Conn: : return: ' msg=conn.recv ' h= Hmac.new (secret_key,msg) digest=h.digest () Conn.sendall (Digest) def Client_handler (ip_port,bufsize=1024 ): tcp_socket_client=socket (Af_inet,sock_stream) tcp_socket_client.connect (ip_port) Conn_auth ( tcp_socket_client) while True: data=input (' >>: '). Strip () if not data:continue if data = = ' Quit ': Break Tcp_socket_client.sendall (Data.encode (' Utf-8 ')) respone=tcp_socket_client.recv (bufsize) Print (Respone.decode (' Utf-8 ')) tcp_socket_client.close () if __name__ = = ' __main__ ': ip_port= (' 127.0.0.1 ', 9999) bufsize=1024 Client_handler (ip_port,bufsize)
Client (illegal: Do not know encryption method)
#_ *_coding:utf-8_*___author__ = ' Linhaifeng ' from socket import *def Client_handler (ip_port,bufsize=1024): tcp_ Socket_client=socket (Af_inet,sock_stream) Tcp_socket_client.connect (ip_port) while True: data=input (' >>: '). Strip () if not data:continue if data = = ' quit ': Break Tcp_socket_client.sendall ( Data.encode (' Utf-8 ')) respone=tcp_socket_client.recv (bufsize) print (Respone.decode (' Utf-8 ')) TCP _socket_client.close () if __name__ = = ' __main__ ': ip_port= (' 127.0.0.1 ', 9999) bufsize=1024 Client_ Handler (ip_port,bufsize)
Client (illegal: do not know Secret_key)
#_ *_coding:utf-8_*___author__ = ' Linhaifeng ' from socket import *import hmac,ossecret_key=b ' Linhaifeng Bang Bang bang1111 ' Def conn_auth (conn): ' Verify client-to-server links :p Aram Conn: : ' Return: ' ' msg=conn.recv ( h=hmac.new (secret_key,msg) digest=h.digest () Conn.sendall (Digest) def Client_handler (Ip_port, bufsize=1024): tcp_socket_client=socket (Af_inet,sock_stream) tcp_socket_client.connect (ip_port) Conn_auth (tcp_socket_client) while True: data=input (' >>: '). Strip () if not data:continue if data = = ' quit ': Break Tcp_socket_client.sendall (Data.encode (' Utf-8 ')) respone=tcp_socket_ CLIENT.RECV (bufsize) print (Respone.decode (' Utf-8 ')) tcp_socket_client.close () if __name__ = = ' __main__ ': ip_port= (' 127.0.0.1 ', 9999) bufsize=1024 Client_handler (ip_port,bufsize)
Two Socketserver implementation concurrency
TCP-based sockets, the key is two loops, a link loop, a communication loop
There are two main classes in the Socketserver module: the server class (solve the link problem) and the request class (to solve the communication problem)
Server class:
Request class:
Inheritance Relationship:
Take the following code as an example to analyze Socketserver Source:
Ftpserver=socketserver. Threadingtcpserver ((' 127.0.0.1 ', 8080), ftpserver)
Ftpserver.serve_forever ()
Order of Lookup properties: Threadingtcpserver->threadingmixin->tcpserver->baseserver
- Instantiate get Ftpserver, first find class Threadingtcpserver __init__, found in TCPServer, and then execute server_bind,server_active
- Find Ftpserver under the Serve_forever, found in Baseserver, and then execute Self._handle_request_noblock (), the method is also in the Baseserver
- Executes Self._handle_request_noblock () and then executes the request, client_address = Self.get_request () (which is self.socket.accept in TCPServer ( ), and then execute self.process_request (Request, client_address)
- Find Process_request in ThreadingMixIn, turn on multithreading to handle concurrency, and execute Process_request_thread, execute self.finish_request (request, Client_ Address
- The above four parts completed the link loop, this section began to enter the processing of the communication section, found in the Baseserver finish_request, triggering our own definition of the class instantiation, to find __init__ method, and our own definition of the class does not have the method, Then go to its parent class, which is baserequesthandler ....
SOURCE Analysis Summary:
TCP-based socketserver in our own defined class.
- Self.server is a Socket object
- Self.request is a link
- Self.client_address is the client address
UDP-based socketserver in our own defined class.
- Self.request is a tuple (the first element is the data sent by the client, the second part is the UDP socket object on the server), such as (b ' adsf ', <socket.socket fd=200, family=addressfamily.af_ INET, Type=socketkind.sock_dgram, proto=0, laddr= (' 127.0.0.1 ', 8080) >)
- Self.client_address is the client address
Ftpserver
Import socketserverimport structimport jsonimport osclass ftpserver (socketserver. Baserequesthandler): coding= ' utf-8 ' server_dir= ' file_upload ' max_packet_size=1024 base_dir=os.path.dirname (OS. Path.abspath (__file__)) def handle (self): print (self.request) while True:data=self.request.re CV (4) data_len=struct.unpack (' I ', data) [0] Head_json=self.request.recv (data_len). Decode (self.coding) Head_dic=json.loads (Head_json) # print (head_dic) cmd=head_dic[' cmd '] if Hasatt R (Self,cmd): Func=getattr (Self,cmd) func (head_dic) def put (Self,args): File_path = Os.path.normpath (Os.path.join (self). Base_dir, Self.server_dir, args[' filename ')) filesize = args[' filesize '] recv _size = 0 Print ('-----> ', File_path) with open (File_path, ' WB ') as F:while Recv_size < fil Esize: Recv_data = Self.request.recv (self.max_packet_size) f.write (recv_data) recv_size + = Len (recv_data) print (' recvsize:%s filesize:%s '% (recv_size, filesize)) Ftpserver=socketserver. Threadingtcpserver ((' 127.0.0.1 ', 8080), Ftpserver) Ftpserver.serve_forever ()
ftpclient
Import socketimport structimport jsonimport osclass mytcpclient:address_family = socket.af_inet Socket_type = Socke T.sock_stream allow_reuse_address = False max_packet_size = 8192 coding= ' utf-8 ' request_queue_size = 5 def __init__ (self, server_address, connect=true): self.server_address=server_address self.socket = Socket.socket (self.address_family, Self.socket_type) if Connect:try: Self.client_connect () Except:self.client_close () Raise Def client_connect ( Self): Self.socket.connect (self.server_address) def client_close (self): Self.socket.close () def run (SE LF): While True:inp=input (">>:"). Strip () if not inp:continue l=inp.split () Cmd=l[0] If Hasattr (self,cmd): Func=getattr (Self,cmd) func (l) def Put (Self,args): CMd=args[0] filename=args[1] if not os.path.isfile (filename): print (' file:%s are NOT exists '%filen AME) return else:filesize=os.path.getsize (filename) head_dic={' cmd ': cmd, ' filename ': OS . Path.basename (filename), ' filesize ': filesize} print (Head_dic) head_json=json.dumps (head_dic) head_jso N_bytes=bytes (head_json,encoding=self.coding) head_struct=struct.pack (' I ', Len (head_json_bytes)) Self.socket. Send (Head_struct) self.socket.send (head_json_bytes) send_size=0 with open (filename, ' RB ') as F: For line F:self.socket.send (line) Send_size+=len (line) print (Send_si Ze) else:print (' upload successful ') client=mytcpclient ((' 127.0.0.1 ', 8080)) Client.run ()
Python Network programming supplement