zoukankan      html  css  js  c++  java
  • socketserver



    一、SocketServer实现并发服务器:       
    • 格式:
    # 定义一个多并发的类,从socketserver模块中BaseRequestHandler类继承 
    class MysocketServer(socketserver.BaseRequestHandler):
    def handle(self):
    # 重写handler方法,名称必须为handler,因为父类中也有handler,只不过该handler为空,client一旦建立连接,则会调用该方法
    # print self.request,self.client_address,self.server
    # self.request 相当于此前的conn
    self.request.sendall(bytes('welcome.',encoding='utf-8'))

    while True:
    # 正常收发交互代码块
    # 用 self.request 代替 conn

    if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()
    • 模拟并发 SSH (ftp代码较多,放于网盘中)
      • =================================server=========================================================
    import subprocess
    import socketserver

    class MysocketServer(socketserver.BaseRequestHandler):

    def handle(self):
    self.request.sendall(bytes('welcome to my server', encoding='utf-8'))

    while True:
    try:
    cmd = self.request.recv(1024).decode()
    if len(cmd) == 0:
    raise Exception('客户端状态发生改变, go to close()')

    # 执行cmd ,获取cmd执行结果
    obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    stdout_data, stderror_data = obj.communicate()
    send_data = stdout_data if len(stderror_data) == 0 else stderror_data

    # 发送 len(data), 获取 ACK
    self.request.sendall(bytes('begin:{}'.format(len(send_data)), encoding='utf-8'))  # 发送给客户端的
    ack = self.request.recv(1024).decode()
    # 发送 data
    if ack.startswith('start'):
    self.request.sendall(send_data)

    except Exception as ex:
    print(ex)
    break

    if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 9998), MysocketServer)
    server.serve_forever()
      • =================================client.py=========================================================
    import socket

    sk = socket.socket()
    sk.connect(('127.0.0.1', 9998,))

    welcome_msg = sk.recv(1024).decode()
    print(welcome_msg)

    while True:
    cmd = input('>> ').strip()
    if len(cmd) == 0:
    continue
    if cmd == 'exit':
    break

    # 发送 cmd 命令
    sk.sendall(bytes(cmd, encoding='utf-8'))
    # 获取 data长度
    recv_data = sk.recv(1024).decode()
    if recv_data.startswith('begin'):
    data_size = int(recv_data.split(':')[-1])
    print('send: {}'.format(data_size))  # 打印需要接收的数据长度

    # 发送ACK确认
    sk.sendall(bytes('start', encoding='utf-8'))

    # 循环接收 data
    recv_size = 0
    recv_data = b''
    while recv_size < data_size:     # 若data长度为0(cd等无返回结果的命令),则直接跳出该循环,既判断了数据是否接收完整,又避免了执行无返回数据命令后client的recv阻塞
    data = sk.recv(1024)
    recv_data += data
    recv_size += len(data)
    else:
    print('recived: {}'.format(recv_size))  # 打印已经接收的数据长度

    print(recv_data.decode('gbk'))

    sk.close()

     




    • 注意:
      • top命令,该命令时一个一直执行的命令,当命令结束,返回结果才能固定
      • 所以,一致会处于等待获取命令执行结果的状态









































  • 相关阅读:
    2017.7.14 使用case when和group by将多条数据合并成一行,并且根据某些列的合并值做条件判断来生成最终值
    2017.7.12 IDEA热部署(更新jsp或java代码不用重启tomcat即可即时生效)
    2017.7.10 Package name does not correspond to the file path
    2017.7.10 Redis报错:DENIED Redis is running in protected mode
    2017.7.10 (windows)redis的安装
    2017.7.7 postgreSQL在插入造成重复时执行更新
    2017.7.1 nginx反向代理服务器域名解析配置(已验证可使用)
    2017.7.1 ftp文件服务器安装与配置(已验证可使用)
    2017.7.1 mysql安装与启动(已验证可以使用)
    日期格式,拼接、跳转,字符集转码(中文乱码)
  • 原文地址:https://www.cnblogs.com/qiaogy/p/5842240.html
Copyright © 2011-2022 走看看