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() # 实例调用用户交互函数
 
原文地址:https://www.cnblogs.com/sunnytomorrow/p/13435884.html