[记录]Python的master-worker和epoll模式
#master-worker模型: #coding:utf-8 import os import sys import socket import time import traceback import errno import signal class Worker(object): def __init__(self, sock): self.sock = sock def accept(self): client, addr = self.sock.accept() client.setblocking(True) self.handle(client, addr) def init_process(self): self.sock.setblocking(False) while True: try: time.sleep(1) self.accept() continue except Exception as e: msg = traceback.format_exc() with open("sub_"+str(os.getpid())+".txt","a") as f: f.write(msg+"\n") if hasattr(e, "errno"): if e.errno not in (errno.EAGAIN, errno.ECONNABORTED, errno.EWOULDBLOCK): msg = traceback.format_exc() else: raise def handle(self, client, addr): data = client.recv(1024) pid = os.getpid() data += str(pid) # print("receive:{} pid:{}".format(data, pid)) client.send("back:"+data) client.close() class Server(object): def __init__(self): self.port = ("127.0.0.1", 8004) self.sock = socket.socket() self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(self.port) self.sock.setblocking(False) self.sock.listen(5) self.WORKERS = {} def run(self): self.init_signals() for i in range(2): self.spawn_worker() print(i) # self.spawn_worker() for k in self.WORKERS: print(k, self.WORKERS[k]) while True: import time time.sleep(3) try: pid, status = os.waitpid(-1, os.WNOHANG) print("kill pid: {}, status: {}".format(pid, status)) except os.error: print("error") def init_signals(self): signal.signal(signal.SIGTTIN, self.incr_one) signal.signal(signal.SIGTTOU, self.decr_one) def incr_one(self, signo, frame): self.spawn_worker() for k in self.WORKERS: print(k, self.WORKERS[k]) def decr_one(self, signo, frame): for k in self.WORKERS: os.kill(k, signal.SIGKILL) break def spawn_worker(self): worker = Worker(self.sock) pid = os.fork() if pid != 0: worker.pid = pid self.WORKERS[pid] = worker return pid worker.pid = os.getpid() worker.init_process() sys.exit(0) if __name__ == "__main__": server = Server() server.run() ======================================================================= epoll模型: server: #-*- coding:utf8 -*- import socket import select import os address = "0.0.0.0" port = 10001 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) def main(): global address,port,sock epoll = select.epoll() #获取创建好的sock的文件描述符 fd = sock.fileno() sock.bind((address,port)) sock_dict = {} sock_dict[fd] = sock #对该sock进行注册 epoll.register(fd,select.EPOLLIN) sock.listen(5) while True: events = epoll.poll(1) for fileno,event in events: #获取到的文件描述符和sock的相同就说明是一个新的连接 if fileno == fd: (client,address) = sock.accept() print address client.setblocking(0) #将新的连接进行注册,用来接收消息 epoll.register(client.fileno(),select.EPOLLIN) sock_dict[client.fileno()] = client elif event & select.EPOLLIN: print "fileno:",fileno data = sock_dict[fileno].recv(128) if data == '你好': print "Data:",data.decode('UTF-8') sock_dict[fileno].send("你好") elif len(data) == 0: print "线路%d已下线"%fileno epoll.unregister(fileno) else: print "Data:",data if __name__ == '__main__': main() client: #coding: UTF-8 import socket import select address = "127.0.0.1" port = 10001 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) def main(): global address,port,sock sock.connect((address,port)) epoll = select.epoll() fd = sock.fileno() #这里的epoll注册只是用来异步接收服务端发过来的消息 epoll.register(fd,select.EPOLLIN) while True: events = epoll.poll(1) for fileno,event in events: if fileno == fd: if event & select.EPOLLIN: data = sock.recv(128) print data data = raw_input(">") if data == 'q': break elif data == '': print "不能发送空消息" continue sock.send(data) sock.close() main()