静态方法
与类无关,不能访问类里的任何属性和方法
类方法
只能访问类变量
属性@property
把一个方法变成静态属性,
flight.status
@status.setter
flight.status = 3
@status.delter
反射
getattr(obj,str)
setattr(obj,str,val)
hasattr(obj,str)
动态导入模块
#lib = __import__('lib.aa') #这是解释器自己内部用的;; #lib.aa import importlib aa = importlib.import_module('lib.aa') #与上面的效果一样,官方建议用 print(aa.C().name)
__new__ ;; ;; __call__
class Foo(obj):
def __call__
print"call"
Foo()()#执行call方法
__metacless__用来定义这个类以怎样的形式被创建;
异常
try
......
except(ValueError,KeyError),e #IN2.7
except(ValueError,KeyError)as e :#3.X
except Exception as e: 放在异常处理的最后面;
else:#没发生异常,就执行
finally ,无论如何都执行
raise ValueErorr
断言assert()
assert type(obj.name) is int print("dddddd")
socket
tcp/ip send,recv
udp
family address
AF.INET ipv4
AF.INET6
AF.UNIX local
socket protocol type
socket .SOCK_STREAM tcp/ip
socket.SOCK_DGRAM 数据报式socket,for UDP
服务端
server = socket.socket(AF.INET,socket.STREAM)
server.bind(localhost,9999)
server.listen()
conn,addr = server.accept() #阻塞
while True:
print(“new conn ”,addr)
data = conn.recv(1024) #8192 #recv 默认阻塞的
if not data:
break #客户端已断开 ,conn.recv收到的都是空数据,
print(data)
conn.send(data.upper())
client
client = socket.socket()
client.connect(serverip,9999)
client.send(data)
client.send(data)
client.recv(data)
ssh例子
socket_server_ssh.py
import os import socket server = socket.socket() server.bind(('localhost',9999)) server.listen() while True: conn,addr = server.accept() print("new conn",addr) while True: print("等待新指令") data = conn.recv(1024) if not data: print("客户端已断开") break print("执行指令:",data) cmd_res = os.popen(data.decode()).read() #接受字符串,执行结果也字符串 print("before send",len(cmd_res)) if len(cmd_res) ==0: cmd_res = "cmd has no output..." conn.send(str(len(cmd_res.encode())).encode("utf-8")) #先发大小给客户端 conn.send(cmd_res.encode("utf-8")) print("send done") server.close()
socket_server_client.py
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) received_size = 0 received_data = b'' while received_size < int(cmd_res_size.decode()): data = client.recv(1024) received_size += len(data) #每次收到的有可能小于1024,所以必须用len判断 print(data.decode()) received_data += data else: print("cmd res receive done...",received_size) print(received_data.decode()) #cmd_res = client.recv(1024) #print(cmd_res) server.close()
socket 粘包
conn.send(str(len(cmd_res.encode())).encode("utf-8")) #先发大小给客户端 #time.sleep(0.5) client_ack = conn.recv(1024) #wait client to confirm conn.send(cmd_res.encode("utf-8"))
ftp server
1.读取文件名
2.检测文件是否存在
3.打开文件
4.检测文件大小
5.发送文件大小客户端
6.等客户端确认
7.开始边读边发数据
8.发送md5
socket 防粘包(linux系统)
socket_server_client.py
import hashlib
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) client.send("准备接受了,loser可以发了".encode()) received_size = 0 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()) reversed_size = 0 filename = cmd.split()[1] f = open(filename,"wb") m = hashlib.md5() while received_size < file_total_size: if file_total_size - received_size >= 1024: #要收不知一次 size = 1024 else: #最后一次,剩多少就收多少; size = file_total_size - received_size print("last receive:",size) data = client.recv(size) 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",received_size,file_total_size) f.close() server_file_md5 = client.recv(1024) print("server file md5:",server_file_md5) print("client file md5:",new_file_md5) client.close()
socket_server_ssh2.py
import hashlib import os,time import socket server = socket.socket() server.bind(('localhost',9999)) server.listen() while True: conn,addr = server.accept() print("new conn",addr) while True: print("等待新指令") data = conn.recv(1024) if not data: print("客户端已断开") break ''' print("执行指令:",data) cmd_res = os.popen(data.decode()).read() #接受字符串,执行结果也字符串 print("before send",len(cmd_res)) if len(cmd_res) ==0: cmd_res = "cmd has no output..." conn.send(str(len(cmd_res.encode())).encode("utf-8")) #先发大小给客户端 #time.sleep(0.5) client_ack = conn.recv(1024) #wait client to confirm conn.send(cmd_res.encode("utf-8"))''' cmd,filename = data.decode().split() print(filename) if os.path.isfile(filename): f = open(filename+".new","rb") m = haslib.md5() file_size = os.stat(filename).st_size conn.send(str(file_size).encode()) #send file size conn.recv(1024) #wait for ack() for line in f: m.update(line) conn.send(line) print("file md5",m.hexdigest()) f.cloce() conn.send(m.hexdigest().encode()) #send() md5 print("send done") server.close()
6. SocketServer
The socketserver
module simplifies the task of writing network servers.
socketserver一共有这么几种类型
1
|
class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate = True )
|
This uses the Internet TCP protocol, which provides for continuous streams of data between the client and server.
1
|
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate = True )
|
This uses datagrams, which are discrete packets of information that may arrive out of order or be lost while in transit. The parameters are the same as for TCPServer
.
1
2
|
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate = True )
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate = True )
There are five classes in an inheritance diagram, four of which represent synchronous servers of four types:
|
+------------+
| BaseServer |
+------------+ | v +-----------+ +------------------+ | TCPServer |------->| UnixStreamServer | +-----------+ +------------------+ | v +-----------+ +--------------------+ | UDPServer |------->| UnixDatagramServer | +-----------+ +--------------------+
创建一个socketserver 至少分以下几步:
- First, you must create a request handler class by subclassing the
BaseRequestHandler
class and overriding itshandle()
method; this method will process incoming requests. - Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.
- Then call the
handle_request()
orserve_forever()
method of the server object to process one or many requests. - Finally, call
server_close()
to close the socket.
1.你必须自己创建一个请求类,并且这个类要继承BaseRequestHanderler,并且还要有重写父类里的Handle();
2.你必须实例化TCPServer,并且传递 server ip 和你上面创建的请求处理类 给这个TCPServer;
server.handle_request() #只处理一个请求
server.serve_forever () #处理多一个请求,永远执行;
例子
#客户端 import socket client = socket.socket() #声明socket类型,同时生成socket对象 client.connect(('localhost',9999)) while True: msg = input(">>:").strip() client.send(msg.encode("utf-8")) #client.send("我要自学".encode("utf-8")) data = client.recv(1024) print("recv:", data.decode()) client.close()
#服务端 import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: self.data = self.request.recv(1024).strip() # self.request is the TCP socket connected to the client #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 # just send back the same data, but upper-cased self.request.send(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9999 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) server.serve_forever()
该服务端
#服务端 import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: try: self.data = self.request.recv(1024).strip() # self.request is the TCP socket connected to the client # 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 ''' # just send back the same data, but upper-cased self.request.send(self.data.upper()) except ConnectionAbortedError as e: print("err",e) break if __name__ == "__main__": HOST, PORT = "localhost", 9999 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
多并发
换成下面这个,就可以多并发了,这样,客户端每连进一个来,服务器端就会分配一个新的线程来处理这个客户端的请求
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #多并发,多线程
#server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)#多进程(linux)
class socketserver.
BaseServer
(server_address, RequestHandlerClass) 主要有以下方法;