目的

  练习socket之间的网路通讯

实现

代码

Server

  import tkinter
  from monitorServer import MonitorServer
  from tkinter import messagebox
  
  
  def main():
      root1 = tkinter.Tk()
      # 给窗口起名字
      root1.title("监控服务器")
      # 设定窗口大小
      root1.geometry("800x50")
      # 锁定大小
      root1.resizable(False, False)
  
      # frame 整体框架设计
      # Top为转换PDF组件
      frame_Top = tkinter.Frame(root1)
      frame_Top.pack(
          side=tkinter.TOP,
          fill=tkinter.X,
      )
      # 添加Label提示选择路径
      l_path = tkinter.Label(
          frame_Top,
          text="本机IP:",
          font=("Arial", 15),
      )
      l_path.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
      # 添加Entry,存放路径
      e_path = tkinter.Entry(frame_Top, )
      e_path.pack(
          side=tkinter.LEFT,
          expand=tkinter.YES,
          fill=tkinter.X,
          pady=10,
      )
      l_path1 = tkinter.Label(
          frame_Top,
          text="端口:",
          font=("Arial", 15),
      )
      l_path1.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
      # 添加Entry,存放路径
      e_path1 = tkinter.Entry(frame_Top, )
      e_path1.pack(
          side=tkinter.LEFT,
          expand=tkinter.YES,
          fill=tkinter.X,
          pady=10,
      )
  
      def closeWindow():
          if not e_path.get():
              messagebox.showinfo("提示:", "IP不能为空")
              return -1
          if not e_path1.get():
              messagebox.showinfo("提示:", "端口不能为空")
              return -1
          M = MonitorServer(e_path.get(), e_path1.get())
          frame_Top.destroy()
          root1.destroy()
          M.monitorServer()
  
      # 添加浏览按钮
      b_select_path1 = tkinter.Button(
          frame_Top,
          text="开启",
          command=lambda: closeWindow(),
          font=("Arial", 12),
      )
      b_select_path1.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
      # 主窗口循环
      root1.mainloop()
  
  
  if __name__ == "__main__":
      main()
  import tkinter
  import socket
  import time
  import threading
  import struct
  from PIL import Image, ImageTk
  
  
  class MonitorServer(object):
      def __init__(self, host, port):
          self.port = port
          self.host = host
  
      def monitorServer(self):
          root = tkinter.Tk()
          # 主程序窗口位置和大小
          root.geometry('1920x1080+0+0')
          width = 1920
          height = 1080
          root.title('远程桌面监控服务端')
          # 用来表示监控软件是否运行的变量
          running = tkinter.IntVar(root, 1)
  
          # 关闭监控窗口时触发的消息处理代码
          def closeWindow():
              running.set(0)
              root.destroy()
  
          root.protocol('WM_DELETE_WINDOW', closeWindow)
          canvas = tkinter.Canvas(root, width=width, height=height)
          canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES)
  
          def updateCanvas(canvas, ):
              global imageId
              sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              print(self.host, self.port)
              sock.bind((str(self.host), int(self.port)))
              sock.listen(5)
              while running.get() == 1:
                  # 自适应当前监控窗口大小
                  width = canvas.winfo_width()
                  height = canvas.winfo_height()
                  conn, addr = sock.accept()
                  tempImageBytes = b''
                  # 图像字节数量
                  len_head = struct.calcsize('I128sI')
                  data = conn.recv(len_head)
                  length, size, sizeLength = struct.unpack('I128sI', data)
                  length = int(length)
                  rest = length
                  bufferSize = 1024 * 10
                  size = eval(size[:int(sizeLength)])
                  while running.get() == 1:
                      if rest > bufferSize:
                          data = conn.recv(1024 * 10)
                      else:
                          data = conn.recv(rest)
                      tempImageBytes += data
                      rest = rest - len(data)
  
                      # 远程桌面截图接收完成,显示图像
                      if rest == 0:
                          tempImage = Image.frombytes('RGB', size, tempImageBytes)
                          tempImage = tempImage.resize((width, height))
                          # tempImage.save('temp.png')
                          tempImage = ImageTk.PhotoImage(tempImage)
                          # 清除上一个截图
                          try:
                              canvas.delete(imageId)
                          except:
                              pass
                          imageId = canvas.create_image(width // 2, height // 2, image=tempImage)
                          # canvas.update()
                          # 通知客户端可以发送下一个截图
                          conn.send(b'ok')
                          print('ok')
                          time.sleep(5)
                          break
  
                  conn.close()
  
          # 使用子线程刷新监控窗口
          t = threading.Thread(target=updateCanvas, args=(canvas,))
          # 主线程关闭时强制关闭刷新窗口的子线程
          t.daemon = True
          t.start()
          root.mainloop()

Client

  import tkinter
  from tkinter import messagebox
  from monitorClient import MonitorClient
  
  if __name__ == "__main__":
      root = tkinter.Tk()
      # 给窗口起名字
      root.title("监控服务器客户端")
      # 设定窗口大小
      root.geometry("800x50")
      # 锁定大小
      root.resizable(False, False)
  
      # frame 整体框架设计
      # Top为转换PDF组件
      frame_Top = tkinter.Frame(root)
      frame_Top.pack(
          side=tkinter.TOP,
          fill=tkinter.X,
      )
      # 添加Label提示选择路径
      l_path = tkinter.Label(
          frame_Top,
          text="监控服务器IP:",
          font=("Arial", 15),
      )
      l_path.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
      # 添加Entry,存放路径
      e_path = tkinter.Entry(frame_Top, )
      e_path.pack(
          side=tkinter.LEFT,
          expand=tkinter.YES,
          fill=tkinter.X,
          pady=10,
      )
      l_path1 = tkinter.Label(
          frame_Top,
          text="端口:",
          font=("Arial", 15),
      )
      l_path1.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
      # 添加Entry,存放路径
      e_path1 = tkinter.Entry(frame_Top, )
      e_path1.pack(
          side=tkinter.LEFT,
          expand=tkinter.YES,
          fill=tkinter.X,
          pady=10,
      )
      # 添加浏览按钮
      b_select_path1 = tkinter.Button(
          frame_Top,
          text="发送",
          command=lambda: closeWindow(),
          font=("Arial", 12),
      )
      b_select_path1.pack(
          side=tkinter.LEFT,
          padx=10,
          pady=10,
      )
  
  
      def closeWindow():
          if not e_path.get():
              messagebox.showinfo("提示:", "IP不能为空")
              return -1
          if not e_path1.get():
              messagebox.showinfo("提示:", "端口不能为空")
              return -1
          M = MonitorClient(e_path.get(), e_path1.get())
          frame_Top.destroy()
          root.destroy()
          M.monitorClient()
  
  
      # 主窗口循环
      root.mainloop()
  import socket
  import struct
  from PIL import ImageGrab
  from tkinter import messagebox
  
  
  class MonitorClient(object):
      def __init__(self, host, port):
          self.port = port
          self.host = host
  
      def monitorClient(self):
          while True:
              try:
                  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                  sock.connect((str(self.host), int(self.port)))
                  # 本地全屏幕截图
                  im = ImageGrab.grab()
                  size = im.size
                  # 发本地截图转换为字节串进行发送
                  imageBytes = im.tobytes()
                  # 发送字节串总长度和图像大小
                  fhead = struct.pack('I128sI', len(imageBytes), str(size).encode(), len(str(size).encode()))
                  sock.send(fhead)
                  rest = len(imageBytes)
                  bufferSize = 1024 * 10
                  while True:
                      if rest > bufferSize:
                          temp = imageBytes[:bufferSize]
                          imageBytes = imageBytes[bufferSize:]
                      else:
                          temp = imageBytes[:]
                      sock.send(temp)
                      rest = rest - len(temp)
                      # 本次截图发送完成
                      if rest == 0:
                          if sock.recv(100) == b'ok':
                              print('ok')
                              break
                  sock.close()
              except:
                  #messagebox.showinfo("提示!", '地址或端口错误,无法连接监控端!')
                  break