zoukankan      html  css  js  c++  java
  • python通过socket实现多个连接并实现ssh功能详解

    python通过socket实现多个连接并实现ssh功能详解

    一、前言
      上一篇中我们已经知道了客户端通过socket来连接服务端,进行了一次数据传输,那如何实现客户端多次发生数据?而服务端接受多个客户端呢?
    二、发送中文信息
      在python3中,socket只能发送bytes类型的数据,bytes类型只能表示0-225的ASCII码的值,并不能表示中文,所以当我们需要发送中文时,需要使用到编码和解码。

    客户端:    
    import socket
    # 客户端
    # 声明协议类型,同时生成socket对象
    client = socket.socket()
    #
    client.connect(('localhost', 8888))
    # python3 接收字节流数据
    msg = input('>>:').strip()
    client.send(msg.encode('utf-8')) # 先编码成utf-8格式
    data = client.recv(1024) # 1024字节的数据
    print(data)
    print(data.decode())

    服务端:    
    import socket
    # 声明协议类型
    server = socket.socket()
    # 绑定本地网卡(多网卡选择),端口
    server.bind(('localhost', 8888))
    # 监听端口
    server.listen() # 监听
    # conn 就是客户端连接后,在服务器端为其生成的一个连接实例
    # address 是客户端的 hostaddr,port
    conn, address = server.accept()
    print("进入等待时间....")
    # 等待
    # print(conn, address)
    print("收到连接....")
    # 接收数据
    data_server = conn.recv(1024)
    print('receive:', data_server.decode()) # 解码
    # 返回一个值
    conn.send(data_server)

    三、Socket实现多个连接

      这个事例需要在Linux环境下测试,在windows中测试时,多个客户端同时连接(也就是同时运行多个socket_client.py程序),其中一个断开,服务端会报错。Linux环境python版本为3.5。

      事例代码:

    客户端:    
    import socket
    # 客户端
    # 声明协议类型,同时生成socket对象
    client = socket.socket()
    #
    client.connect(('localhost', 8888))
    # python3 接收字节流数据
    while True:
      msg = input('>>:').strip()
      if len(msg) == 0:   # 输入不能为空
        continue
      client.send(msg.encode('utf-8'))
      data = client.recv(1024) # 1024字节的数据
      print(data)
      print(data.decode())

      事例中输入为空(即len(msg==0))是不可以的,如果不输入任何东西,socket程序默认等待你的输入,所以程序会卡掉。

    服务端:    
    # -*- coding: UTF-8 -*-
    import socket
    # 声明协议类型
    server = socket.socket()
    # 绑定本地网卡(多网卡选择),端口
    server.bind(('localhost', 8888))
    # 监听端口
    server.listen(5) # 监听
    while True:
      conn, address = server.accept()
      print("进入等待时间....")
      while True:
        print("收到连接....")
        # 接收数据
        data_server = conn.recv(1024)
        if not data_server:  # 这里判断客户端断开的情况,不控制会无限循环
          print('client is lost...')
          break
        print('receive:', data_server.decode())
        # 返回一个值

    conn.send(data_server)


    在Linux服务器上,我开启了6个客户端,每个客户端输入一次就断开(即显示了client has lost...),服务端分别和六个客户端连接并接收数据。
    四、实现ssh功能
    4.1 测试环境
      服务端: 172.16.200.49,监听端口('0.0.0.0', 8888),Linux系统
      客户端:本机win10
    4.2 测试代码
      服务端:    
    # -*- coding: UTF-8 -*-
    import socket
    import os
    # 声明协议类型
    server = socket.socket()
    # 绑定本地网卡(多网卡选择),端口
    server.bind(('0.0.0.0', 8888))
    # 监听端口
    server.listen() # 监听
    while True:
      conn, address = server.accept()
      print("进入等待时间....")
      while True:
        print("收到连接....")
        # 接收数据
        data_server = conn.recv(1024)
        if not data_server:
          print('client is lost...')
          break
        res = os.popen("{}".format(data_server.decode())).read() # 将执行命令的结果存储返回
        # 返回结果
        conn.send(res.encode('utf-8'))

      客户端:    
    # -*- coding: UTF-8 -*-
    import socket
    # 客户端
    # 声明协议类型,同时生成socket对象
    client = socket.socket()
    #
    client.connect(('172.16.200.49', 8888)) # 服务端ip和端口
    # python3 接收字节流数据
    while True:
      msg = input('>>:').strip()
      if len(msg) == 0:
        continue
      client.send(msg.encode('utf-8'))
      data = client.recv(1024) # 1024字节的数据
      print(data.decode())

      结果如下:

    注:socket中recv()和send()函数接收和发送数据大小都是有限制的。如果一次发送太大,客户端接收不完,就会先存储在缓存当中。但是下一次命令,客户端接收的还是上次命令没有发完的数据。
    四、模拟FTP上传文件
      本例当服务端在Linux环境中,struck模块有些问题....,目前在win10中可以正常运行
      服务端:     
    # -*- coding: UTF-8 -*-
    import struct
    import socket
    class FtpServer(object):
      def __init__(self, host, port):
        self.host = host
        self.port = port
      def ftp_server(self):
        # 声明协议类型
        ftp_server = socket.socket()
        # 绑定本地网卡(多网卡选择),端口
        ftp_server.bind((self.host, self.port))
        # 监听端口
        ftp_server.listen() # 监听
        while True:
          print('等待...')
          conn, address = ftp_server.accept()
          while True:
            file_info = struct.calcsize('128sl')
            buf = conn.recv(file_info)
            if buf:
              file_name, file_size = struct.unpack('128sl', buf)
              # 使用strip()删除打包时附加的多余空字符
              file_new_name = file_name.decode().strip('0')
              print('start receiving...')
              fw = open(file_new_name, 'wb')
              received_size = 0 # 接收文件的大小
              while not received_size == file_size:
                if file_size - received_size > 1024:
                  r_data = conn.recv(1024)
                  received_size = len(r_data)
                else:
                  r_data = conn.recv(file_size - received_size)
                  received_size = file_size
                fw.write(r_data)
              fw.close()
    if __name__ == '__main__':
      server = FtpServer('localhost', 8888)
      server.ftp_server()

      客户端:    
    # -*- coding: UTF-8 -*-
    import socket
    import os
    import struct
    class FtpClient(object):
      # 定义一个FtpClien类
      def __init__(self, host, port):
        self.host = host
        self.port = port
      def client_push(self):
        # 声明协议类型,同时生成socket对象
        ftp_client = socket.socket()
        # 连接服务端
        ftp_client.connect((self.host, self.port))
        while True:
          # 切换文件目录路径
          print("输入文件目录路径")
          pwd = input(">>:").strip()
          # 列出文件名称
          files_list = os.listdir('{}'.format(pwd))
          for i in files_list:
            print(i)
          file_name = input('输入上传的文件名:').strip()
          file_path = os.path.join(pwd, file_name)
          if os.path.isfile(file_path):
            file_info = struct.calcsize('128sl') # 定义打包规则
            f_head = struct.pack('128sl', file_name.encode('utf-8'), os.stat(file_path).st_size)
            ftp_client.send(f_head)
            fo = open(file_path, 'rb')
            while True:
              file_data = fo.read(1024)
              if not file_data:
                break
              ftp_client.send(file_data)
            fo.close()
            # 上传文件
            ftp_client.send(file_data)
    # client.close()
    if __name__ == '__main__':
      client = FtpClient('localhost', 8888)
      client.client_push()

      结果:

    在socket_server.py文件位置处能看到上传的文件

    总结

    以上就是本文关于python通过socket实现多个连接并实现ssh功能详解的全部内容,希望对大家有所帮助。


  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/amengduo/p/9586258.html
Copyright © 2011-2022 走看看