10 Python编程:从入门到实践---socket&socketserver

socket基本语法

server端配置

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import socket
 6 
 7 server = socket.socket()
 8 server.bind(('localhost',6969))
 9 server.listen()
10 
11 print("我要开始等电话了")
12 conn,addr = server.accept() #等连接进来
13 print(conn,addr)
14 
15 print("电话来了")
16 data = conn.recv(1024)
17 print("recv:",data)
18 conn.send(data.upper())
19 
20 server.close()
View Code

client端配置

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import socket
 6 
 7 client = socket.socket()   #声明socket类型,同时生成socket连接对象
 8 client.connect(('localhost',6969))
 9 
10 client.send(b"hello world!")
11 data = client.recv(1024)
12 print("rece:",data)
13 
14 client.close()
View Code

实例一:模拟ssh登录服务器,输入命令将命令结果返回客户端

代码过程:

  1、server端监听客户端发来的命令

  2、服务端将命令通过os.popen方法将内容字符长度和命令内容返回给客户端

  3、客户端接收server端返回的命令字符长度,因为有可能一次长度超过1024,需要多次从缓冲区传输

ssh server 端代码

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import os
 6 import socket
 7 
 8 server = socket.socket()
 9 server.bind(('localhost',9999))
10 server.listen()
11 
12 while True:
13     conn,addr = server.accept()
14     while True:
15         data = conn.recv(1024)  #接收客户端发来的数据请求
16         if not data: #如果客户端发来的数据请求内容为空,则终止这次循环
17             break
18         cmd_res = os.popen(data.decode()).read()
19         if len(cmd_res) == 0:
20             cmd_res = "cmd has no output...."
21         conn.send(str(len(cmd_res.encode())).encode("UTF-8"))  #发送了一个返回结果的字符长度
22         conn.send(cmd_res.encode("UTF-8"))  #并且将返回内容发送过去
23     server.close()
View Code

ssh client端代码

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import socket
 6 
 7 client = socket.socket()
 8 client.connect(('localhost',9999))
 9 
10 while True:
11     cmd = input(">>")
12     if len(cmd) == 0:
13         continue
14     client.send(cmd.encode("UTF-8"))
15     cmd_res_size = client.recv(1024)  #收到服务端返回的字符大小
16     print("返回结果的字符大小为:",cmd_res_size)
17     received_size = 0
18     received_data = b''
19     while received_size < int(cmd_res_size.decode()):   #如果命令结果小于发送过来字符总大小就进行循环
20         cmd_res_msg = client.recv(1024)     #返回命令结果内容
21         received_size += len(cmd_res_msg)   #收到的内容可能小于1024
22         received_data += cmd_res_msg
23     else:
24         print("cmd res receive done....",received_size)
25         print(received_data.decode())
26 client.close()
View Code

 实例二:通过socket实现文件发送

代码过程:

  1. 读取文件名
  2. 检测文件是否存在
  3. 打开文件
  4. 检测文件大小
  5. 发送文件大小给客户端
  6. 等客户端确认
  7. 开始边读边发数据
  8. 发送md5校验

ftp server端代码:

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 import os
 5 import socket
 6 import hashlib
 7 
 8 
 9 server = socket.socket()
10 server.bind(('0.0.0.0',9099))
11 server.listen()
12 
13 while True:
14     conn,addr = server.accept()
15     while True:
16         data = conn.recv(1024)
17         if not data:
18             break
19         print(data)
20         cmd,filename = data.decode().split()
21         if os.path.isfile(filename):
22             f = open(filename,"rb")
23             m = hashlib.md5()
24             file_size = os.stat(filename).st_size
25             conn.send(str(file_size).encode())
26             conn.recv(1024)    #接收客户端防止粘包发送的内容
27             for line in f:
28                 m.update(line)
29                 conn.send(line)
30             #print("file md5",m.hexdigest())
31             f.close()
32             conn.send(m.hexdigest().encode())
33     server.close()
View Code

ftp client端代码:

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 
 5 import socket
 6 import hashlib
 7 client = socket.socket()
 8 client.connect(('localhost',9099))
 9 
10 while True:
11     cmd = input(">>>").strip()
12     if len(cmd) == 0:
13         continue
14     if cmd.startswith("get"):
15         client.send(cmd.encode())
16         server_response = client.recv(1024)    #接收server端判断的数据文件大小
17         print(server_response)     #打印server端判断的数据文件大小
18         client.send(b"ready to rece file")     # 目的是防止粘包
19         file_total_size = int(server_response.decode())   #将server发送文件内容进行解码并转换成整数
20         received_size = 0    #初始化变量文件大小为0
21         filename = cmd.split()[1]    #获取客户端输出的文件名称
22         f = open(filename + ".new","wb")      #将从server端读取的文件,写入到新文件
23         m = hashlib.md5()
24         while received_size < file_total_size:    #每次串1024字符
25             if file_total_size - received_size > 1024:
26                 size = 1024
27             else:
28                 size = file_total_size - received_size    #当不满1024个字符也一次发送过去
29 
30             data = client.recv(size)
31             received_size += len(data)
32             m.update(data)
33             f.write(data)
34             #print(file_total_size,received_size)
35         else:
36             new_file_md5 = m.hexdigest()
37             print("file rece done",received_size,file_total_size)
38             f.close()
39         sever_file_md5 = client.recv(1024)
40         print("server file md5:",sever_file_md5)
41         print("client file md5:",new_file_md5)
42 
43 client.close()
View Code

执行结果如下:出现了以.new结尾的文件,并且md5校验码相同,说明两个文件内容相同

socketserver级别操作

 1 #!/usr/bin/evn python
 2 # --*-- coding: utf-8 --*--
 3 # Auther : Liu WeiDong
 4 import socketserver
 5 
 6 
 7 class MyTCPHandler(socketserver.BaseRequestHandler):
 8     def handle(self):
 9         while True:
10             try:
11                 self.data = self.request.recv(1024).strip()
12                 print("{} wrote:".format(self.client_address[0]))
13                 print(self.data)
14                 self.request.send(self.data.upper())
15             except ConnectionError as e:
16                 print("err",e)
17                 break
18 if __name__ == "__main__":
19     HOST,PORT = "localhost",9999
20     server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)
21     server.serve_forever()
View Code

 

posted @ 2022-07-12 09:54  摩天居士-谢烟客  阅读(68)  评论(0编辑  收藏  举报