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() # 实例调用用户交互函数