Python uses Asyncore to implement the socket server client

Source: Internet
Author: User
Tags signal handler

#!/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

#配置和日志部分, modify according to your needs
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 ')

# server that handles commands
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 ' {1} Bytes '. Format (New_filename, filesize))
recvd_size = 0 # Defines the size of the received file
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


# server that handles transferring files
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):
# Execute Command
If Self.message is not None:
Cmds = {}
Sent_size = 1014 # The JSON is added with 10 characters after stitching
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:]
# Make sure writable is true
Self.buffer = self.message[sent_size:]
# Transferring files
If Self.filepath is not None:
While True:
If Os.path.isfile (Self.filepath):
# define the definition file information. 128s means the file name is 128bytes long, l represents an int or log file type, where file size, plus ">" symbol is to resolve Windows Linux inter-pass exception
Fileinfo_size = struct.calcsize (' &GT;128SL ')
# defines header information, including file name and file size
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编写, this is just part of the implementation.
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))

Python uses Asyncore to implement the socket server client

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.