Python--socket
socket网络编程:socket、socketserver
socket:{server,client}
socket_server示例:
1 import socket # 导入模块 2 server = socket.socket() #实例化一个server 3 server.bind(('localhost', 6969)) # 绑定监听的地址和端口 4 server.listen() # 开始监听 5 while True: # 循环等待客户端的连接,当一个连接断开后,继续等待下个客户端的连接 6 coon, addr = server.accept() # 等待客户端的连接,当有客户端连接时,conn,addr才有值 7 while True: # 循环接收客户端的数据 8 data = coon.recv(1024) #接收客户端的数据,接收数据大小为1K 9 print("server recv:", data.decode()) #接收到的数据类型为b,需要decode 10 if not data: # 如果无数据,则代表客户端断开 11 print("client is lost...") 12 break # 与客户端断开,等待下次客户端的连接 13 coon.send(data.upper()) # 向客户端发送数据,注意将发送的数据encode(),此处data即为b类型,所以不需要 14 server.close() # 实例关闭
socket_client示例:
import socket #导入模块 client = socket.socket() # 创建客户端实例 client.connect(('localhost', 6969)) # 实例连接服务端地址及端口 while True: # 循环接收用户输入并发送 msg = input(">>:").strip() # 等待用户输入 if len(msg.strip()) == 0: # 如果用户输入为空,则继续让用户输入 continue client.send(msg.encode("utf-8")) # 将用户输入发送只server端 data = client.recv(1024) # 接收server端发送的数据 print("recv:", data.decode()) client.close() # 客户端关闭
应用:
1、 使用socket实现类似ssh登录后执行命令的操作
socket_ssh_server
1 import socket,os,time # 导入模块 2 server = socket.socket() # 实例化server 3 server.bind(('localhost',9999)) # server绑定地址和端口 4 server.listen() # 监听 5 while True: 6 conn, addr = server.accept() # 等待客户端的连接 7 print("new conn:",addr) 8 while True: 9 print("等待新指令") 10 data = conn.recv(1024) # 接收客户端的指令 11 if not data: 12 print("客户端已断开") 13 break 14 print("执行指令:",data) 15 cmd_res = os.popen(data.decode()).read() #使用os.popen执行收到的指令,返回结果赋值给cmd_res 16 print("before send",len(cmd_res)) # 输出命令的长度 17 if len(cmd_res) ==0: # 如果指令结果长度为0,则没此命令 18 cmd_res = "cmd has no output..." 19 conn.send( str(len(cmd_res.encode())).encode("utf-8")) #先发大小给客户端 20 conn.recv(1024) # 等待客户端确认,防止发送指令大小和发送结果出现粘包现象 21 conn.send(cmd_res.encode("utf-8")) # 发送指令输出结果 22 print("send done") 23 server.close()
socket_ssh_client
1 import socket # 导入模块 2 client = socket.socket() # 实例化客户端 3 client.connect(('localhost', 9999)) # 连接服务端 4 while True: # 循环接收用户输入 5 data = input(">>:").strip() 6 if len(data) == 0:continue 7 client.send(data.encode("utf-8")) # 发送指令 8 result_data_size = client.recv(1024) # 接收执行返回结果的大小 9 print(result_data_size.decode()) 10 client.send(b"please send cmd result") 11 recv_data_size = 0 12 recv_data = b"" 13 while recv_data_size < int(result_data_size.decode()): # 当指令结果大小大于1024时,循环接收指令结果 14 recv_data_block = client.recv(1024) 15 recv_data_size += len(recv_data_block) 16 recv_data += recv_data_block 17 else: 18 print(recv_data_size) 19 print(recv_data.decode()) 20 client.close()
2、 使用socket实现文件发送并计算MD5值
socket_file_server
1 import socket, os, hashlib #导入模块 2 server = socket.socket() 3 server.bind(("localhost", 9999)) 4 server.listen() 5 while True: 6 conn, addr = server.accept() 7 print("新连接:", addr) 8 while True: 9 print("等待指令") 10 data = conn.recv(1024) 11 if not data: 12 print("客户端已断开") 13 break 14 filename = data.split()[1] 15 print("文件名:", filename) 16 m = hashlib.md5() 17 if os.path.isfile(filename): 18 file_size = os.stat(filename).st_size 19 conn.send(str(file_size).encode()) 20 conn.recv(1024) 21 print("等待接收端确认") 22 f = open(filename, "rb") 23 for line in f: 24 m.update(line) 25 conn.send(line) 26 f.close() 27 conn.send(m.hexdigest().encode()) 28 print("file send done") 29 server.close()
socket_file_client
1 import socket, hashlib 2 client = socket.socket() 3 client.connect(("localhost", 9999)) 4 while True: 5 cmd = input(">>:").strip() 6 if len(cmd) == 0:continue 7 if cmd.startswith("get"): 8 client.send(cmd.encode()) 9 filename = cmd.split()[1] 10 res_filesize = client.recv(1024).decode() 11 print("文件总大小是",res_filesize) 12 client.send("please send".encode()) 13 m = hashlib.md5() 14 recv_size = 0 15 f = open(filename+"new","wb") 16 while recv_size < int(res_filesize): 17 if int(res_filesize) - recv_size > 1024: # 解决文件发送与MD5发送的粘包问题 18 size = 1024 19 else: 20 size = int(res_filesize) - recv_size 21 data = client.recv(size) 22 recv_size += len(data) 23 m.update(data) 24 f.write(data) 25 else: 26 print("文件接收完毕,源文件大小%s,已接收文件大小%s" % (res_filesize,recv_size)) 27 old_file_md5 = client.recv(1024).decode() 28 f.close() 29 print("new file md5: ", m.hexdigest()) 30 print("old file md5: ", old_file_md5) 31 client.close()
3、 socketserver示例
socketserver_server
1 import socketserver # 导入模块 2 class MyTcpSocketServer(socketserver.BaseRequestHandler): # 创建一个类,继承socketserver.BaseRequestHandler 3 def handle(self): # 重写handle方法 4 print(self.client_address) 5 while True: 6 try: #抓取客户端断开的异常 7 self.data = self.request.recv(1024).strip() # 接收客户端的数据 8 self.request.send(self.data.upper()) # 发送数据给客户端 9 except ConnectionResetError as e: 10 print("Error:", e) 11 break 12 13 if __name__ == "__main__": 14 HOST, PORT = "localhost", 9889 15 print(">>>>等待新连接>>>>") 16 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTcpSocketServer) #实例化,ThreadingTCPServer可以实现多用户同时交互 17 server.serve_forever() # 永久接收客户端的请求
socketserver_client:直接使用socket模块即可
1 import socket 2 client = socket.socket() 3 client.connect(("localhost",9889)) 4 while True: 5 data = input(">>:").strip() 6 if len(data) == 0:continue 7 client.send(data.encode()) 8 recv_data = client.recv(1024) 9 print(recv_data) 10 client.close()
进阶
使用面向对象实现客户端文件上传到服务器端
socketserver_server
1 import socketserver,json,os # 导入模块 2 3 class MyTcpServer(socketserver.BaseRequestHandler): # 创建socketserver类 4 5 def put(self,*args): # 接收文件函数 6 file_dic = args[0] 7 filename = file_dic["filename"] 8 filesize = file_dic["size"] 9 if os.path.isfile(filename): 10 f = open(filename+".new","wb") 11 else: 12 f = open(filename,"wb") 13 self.request.send(b"please send") 14 recv_size = 0 15 while recv_size < int(filesize): 16 data = self.request.recv(1024) 17 f.write(data) 18 recv_size += len(data) 19 else: 20 print("接收完成") 21 22 def handle(self): # 重写handle方法 23 while True: 24 try: 25 self.data = self.request.recv(1024).strip() 26 file_dic = json.loads(self.data.decode()) 27 action = file_dic["action"] 28 if hasattr(self,action): # 使用反射 29 func = getattr(self,action) 30 func(file_dic) 31 else: 32 print("no action:", action) 33 except Exception as e: 34 print(e) 35 break 36 37 if __name__ == "__main__": 38 HOST,PORT = "localhost", 9999 39 server = socketserver.ThreadingTCPServer((HOST,PORT), MyTcpServer) 40 server.serve_forever()
socketserver_client
1 import socket,os,json # 导入模块 2 class MyFtpClient(object): # 定义客户端类 3 def __init__(self): 4 self.client = socket.socket() # 客户端初始化 5 6 def connect(self,ip,port): 7 self.client.connect((ip,port)) # 连接服务端 8 9 def interactive(self): 10 while True: # 循环接收用户输入 11 cmd = input(">>:").strip() 12 if len(cmd)==0:continue 13 cmd_split = cmd.split() 14 action = cmd_split[0] 15 if hasattr(self,action): # 使用反射判断有无用户输入的指令,没有时返回help 16 func = getattr(self,action) 17 func(cmd_split) 18 else: 19 self.help() 20 21 def help(self): 22 msg = ''' 23 ls 24 pwd 25 put filename 26 cd ../.. 27 ''' 28 print(msg) 29 def put(self,*args): # 上传函数 30 cmd_split = args[0] 31 filename = cmd_split[1] 32 if os.path.isfile(filename): # 使用os模块判断文件是否存在 33 filesize = os.stat(filename).st_size 34 file_dic = { 35 "action": "put", 36 "filename": filename, 37 "size": filesize, 38 "overridden": True 39 } 40 self.client.send(json.dumps(file_dic).encode('utf-8')) 41 self.client.recv(1024) 42 f = open(filename,"rb") 43 for line in f: 44 self.client.send(line) 45 else: 46 print("send done") 47 else: 48 print(filename,"is nor exist") 49 50 client = MyFtpClient() # 实例化客户端 51 client.connect("localhost",9999) # 实例连接服务端 52 client.interactive() # 实例调用用户交互函数