python使用asyncore实现socket server client

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @CreateTime : 2018/5/29
# @Author : 593703
# @File : server_client.py
# @Software : sc
# @since : 0.0.1
# @Desc : socket server and client
# @license : Copyright (c) 2018, Inc. All rights reserved.
# @Contact : [email protected]

import os
import sys

sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir))
import asyncore
import subprocess
import socket
import struct
import errno
from sfo_common.import_common import *
from agent.agent import *
from threading import Event

#配置和日志部分,按自己需求修改
config = Config()
logging.config.fileConfig(config.logging_conf)
logger = logging.getLogger("server")
util = Util()
evt = Event()
class Util(object):
def __init__(self):
pass

def ensure_dir(self, pathname):
dirname = os.path.dirname(pathname)
if not os.path.exists(dirname):
os.makedirs(dirname)


def excute_command(self, cmdstr):
try:
process = subprocess.Popen(cmdstr, stdout=subprocess.PIPE, shell=True)
stdout, stderr = process.communicate()
if process.returncode == 0:
if len(stdout) == 0:
return 'SUCCESS'
return str(stdout).strip()
elif process.returncode == 1:
if stdout is None:
return 'Operation not permitted'
else:
return stdout
else:
print "RC: %s" % process.returncode
print stdout
raise Exception("stderr: %s" % str(stderr))
except Exception as ex:
logger.info("excute_command function excute exception:" + str(ex))

def exct_cmd(self, cmdstr):
process = subprocess.Popen(cmdstr, stdout=subprocess.PIPE, shell=True,stderr=subprocess.STDOUT)
res = process.stdout.readlines()
process.stdout.flush()
process.stdout.close()
return res


class ClusterCommandHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(1024)
self.out_buffer += data

def writable(self):
return (len(self.out_buffer) > 0)

def handle_write(self):
res = {}
if len(self.out_buffer) > 0:
if len(self.out_buffer) > 1024:
excute_cmd = ''
while len(self.out_buffer) > 0:
cmdstr = self.out_buffer[:1024]
if util.is_json(cmdstr):
param = json.loads(cmdstr, encoding='utf-8')
excute_cmd += param['cmd']
self.out_buffer = self.out_buffer[1024:]
result = util.excute_command(excute_cmd)
if len(result) > 512:
while 1:
rec = result[:512]
result = result[512:]
if not result:
if len(rec) > 0:
self.send(bytes(rec))
logger.info(rec)
break
self.send(bytes(rec))
logger.info(rec)
else:
rec = result[:512]
self.send(bytes(rec))
logger.info(rec)
else:
if util.is_json(self.out_buffer):
bsize = len(self.out_buffer)
param = json.loads(self.out_buffer, encoding='utf-8')
self.out_buffer = self.out_buffer[bsize:]
if param.has_key('cmd'):
result = util.excute_command(param['cmd'])
if len(result) > 512:
while 1:
rec = result[:512]
result = result[512:]
if not result:
if len(rec) > 0:
self.send(bytes(rec))
logger.info(rec)
break
self.send(bytes(rec))
logger.info(rec)
else:
rec = result[:512]
self.send(bytes(rec))
logger.info(rec)
else:
self.send('Error params')
logger.info('Error params')

# 处理命令的服务器
class ClusterCommandServer(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
host = socket.gethostname()
port = config.sock_cmd_port
self.bind((host, port))
self.listen(5)

def handle_accept(self):
pair = self.accept()
if pair is not None:
conn, addr = pair
logger.info('Incoming connection from %s' % repr(addr))
handler = ClusterCommandHandler(conn)

class ClusterFileHandler(asyncore.dispatcher_with_send):
def handle_read(self):
while 1:
fileinfo_size = struct.calcsize('>128sl')
buf = self.recv(fileinfo_size)
if buf:
filename, filesize = struct.unpack('>128sl', buf)
fn = filename.strip('\00')
util.ensure_dir(config.temp_file)
new_filename = os.path.join(config.temp_file, fn)
if os.path.exists(new_filename):
os.remove(new_filename)
logger.info('file new name is {0}, filesize is {1} Bytes'.format(new_filename, filesize))
recvd_size = 0 # 定义已接收文件的大小
fp = open(new_filename, 'wb')

while not recvd_size == filesize:
try:
if filesize - recvd_size > 1024:
data = self.recv(1024)
recvd_size += len(data)
else:
data = self.recv(filesize - recvd_size)
recvd_size = filesize
except IOError,error:
if error.errno == errno.EWOULDBLOCK:
pass
else:
fp.write(data)

fp.close()
self.out_buffer = fn
break

def handle_write(self):
try:
res = {}
if len(self.out_buffer) > 0:
res['file'] = self.out_buffer
self.out_buffer = ''
res['status'] = 'OK'
res['result'] = 'File receive compeled'
rec = json.dumps(res, encoding='utf-8', ensure_ascii=True)
self.send(rec)
logger.info(rec)
except socket.error as e:
raise e


# 处理传输文件的服务器
class ClusterFileServer(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
host = socket.gethostname()
port = config.sock_file_port
self.bind((host, port))
self.listen(5)

def handle_accept(self):
pair = self.accept()
if pair is not None:
conn, addr = pair
logger.info('Incoming connection from %s' % repr(addr))
handler = ClusterFileHandler(conn)


class ClusterClient(asyncore.dispatcher):
def __init__(self, host='127.0.0.1', port=9999, message=None, filepath=None):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = port
self.message = message
self.filepath = filepath
self.buffer = '__wait__'
self.content = ''
self.connect((self.host, self.port))

def handle_connect(self):
pass

def handle_close(self):
self.close()

def handle_read(self):
data = self.recv(512)
if len(data) > 0 and len(data) < 512:
self.buffer += data
self.handle_close()
else:
self.buffer += data




def writable(self):
return (len(self.buffer) > 0)

def handle_write(self):
# 执行命令
if self.message is not None:
cmds = {}
sent_size = 1014 # 拼接后json化会加上10个字符
if len(self.message[:sent_size]) > 0:
cmds['cmd'] = self.message[:sent_size]
cmdstr = json.dumps(cmds, encoding='utf-8', ensure_ascii=True)
sent = self.send(cmdstr)
self.message = self.message[sent_size:]
# 确保writable为True
self.buffer = self.message[sent_size:]
# 传输文件
if self.filepath is not None:
while True:
if os.path.isfile(self.filepath):
# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小,加">"符号是解决windows linux互传时出现异常
fileinfo_size = struct.calcsize('>128sl')
# 定义文件头信息,包含文件名和文件大小
fhead = struct.pack('>128sl', os.path.basename(self.filepath),
os.stat(self.filepath).st_size)
self.send(fhead)
logger.info('client filepath: {0}'.format(self.filepath))

with open(self.filepath, 'rb') as fp:
while 1:
data = fp.read(1024)
if not data:
logger.info('{0} file send over...'.format(self.filepath))
self.filepath = None
self.buffer = ''
break
self.send(data)
break

if self.buffer is not None:
if self.buffer == '__wait__':
self.buffer = ''
else:
pass


def handler(signum, frame):
logger.info("Signal handler called with signal, {}. Set the internal flag to true for Event.".format(signum))
evt.set()

#agent参考上一篇agent编写,这里只是实现部分
class ServerAgent(Agent):
def __init__(self, pidfile):
Agent.__init__(self, pidfile)

def run(self):
server1 = ClusterCommandServer()
server2 = ClusterFileServer()
asyncore.loop()
signal.signal(signal.SIGTERM, handler)
while not evt.isSet():
evt.wait(600)
logger.info("ServerAgent stoped")


if __name__ == '__main__':
  #配置文件路径修改为自己的文件路径
agent = ServerAgent(config.server_agnet_pfile)
try:
if len(sys.argv) == 3:
if 'server' == sys.argv[1]:
if 'start' == sys.argv[2]:
agent.start()
if 'stop' == sys.argv[2]:
agent.stop()
elif 'client' == sys.argv[1]:
if 'start' == sys.argv[2]:
#client = ClusterClient(host='10.202.127.4', port=7201, message='systemctl start openstack-swift-container-auditor')
client = ClusterClient(host='10.202.127.4', port=7202, filepath='/tmp/123/1.txt')
asyncore.loop()
print client.buffer
else:
print("Unknown command")
sys.exit(2)
else:
print("usage: %s" % (sys.argv[0],))
sys.exit(2)
except Exception as ex:
logger.info("cluster server client run exception:" + str(ex))

猜你喜欢

转载自www.cnblogs.com/chmyee/p/9208144.html