Exemple #1
0
def getBody(socket_obj):
    s = SocketParser()
    header = s.getHeader(socket_obj)
    if header['cmd'] == 0:
        return False
    body = s.getBody(socket_obj, header['body_len'])
    return body
Exemple #2
0
def getBody(socket_obj):
    s = SocketParser()
    header = s.getHeader(socket_obj)
    if header['cmd'] == 0:
        return False
    body = s.getBody(socket_obj, header['body_len'])
    return body
Exemple #3
0
 def __init__(self, app=""):
     self.__app = app
     self.__socket_parser = SocketParser()
Exemple #4
0
class Server:

    # 白名单列表, 默认允许本机连接
    __allow_ip = ["127.0.0.1"]
    # epoll对象
    __epoll = ""
    # socket链接
    __socket = ""
    # 超时时间设置,客户端10秒内没有任何输入,系统会自动断开
    # 从第一次有输入后的10秒开始计时,第一次输入的10秒不计时
    # __timeouts = 5 #秒数
    # 监听主机IP, 默认监听
    __host = "0.0.0.0"
    # 监听主机端口,默认为8888
    __port = 8888
    # 等待连接队列的最大长度
    __listens = 1024
    # 设置阻塞模式,1阻塞模式 0非阻塞模式, 默认非阻塞模式
    __block = 0
    # 连接列表,值为:socket对象
    __client_connections = {}
    # 连接IP列表
    __client_ip = {}
    # 连接接受信息列表
    __client_requests = {}
    # 注册的应用程序
    __app = ""
    # socket解析对象
    __socket_parser = ""
    # 发送给client的数据
    __send_list = ""

    def __init__(self, app=""):
        self.__app = app
        self.__socket_parser = SocketParser()

    # 设置白名单,默认运行本机IP
    def setAllowIp(self, ip_list=[]):
        if len(ip_list) > 0:
            for lv in ip_list:
                self.__allow_ip.append(lv)

    # 检测IP是否在白名单里
    def __isAllowIp(self, ip):
        if len(self.__allow_ip) == 0:
            return False
        else:
            try:
                # 如果存在返回True,否则抛出异常
                self.__allow_ip.index(ip)
                return True
            except:
                return False

    # 服务监听
    def listen(self, port=0):
        # 创建socket链接
        self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 在绑定前让套接字允许复用(两个套接字可以绑定到同一个端口上)
        self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 绑定主机和端口
        if port == 0:
            port = self.__port
        self.__socket.bind((self.__host, int(port)))
        # 等待连接队列的最大长度
        self.__socket.listen(self.__listens)
        # 设置阻塞模式,默认为非阻塞模式
        self.__socket.setblocking(self.__block)
        # 创建epoll对象
        self.__epoll = select.epoll()
        self.__epoll.register(self.__socket.fileno(), select.EPOLLIN | select.EPOLLET)  # 工作在ET模式
        # 开始服务
        self.__loop()

    # 开始服务
    def __loop(self):
        try:
            while True:
                events = self.__epoll.poll(-1)
                # print("polling...")
                # print(events)
                for fileno, event in events:
                    # 当请求连接时(处理客户端链接)
                    # 只有客户端第一次建立链接时会执行一次
                    if fileno == self.__socket.fileno():
                        try:
                            while True:
                                conn_sock, client_values = self.__socket.accept()
                                # print("accept...")
                                client_ip, client_port = client_values
                                conn_sock.setblocking(0)
                                # 检测白名单
                                if not self.__isAllowIp(client_ip):
                                    conn_sock.close()  # 关闭链接
                                    break
                                conn_fileno = conn_sock.fileno()
                                self.__epoll.register(conn_fileno, select.EPOLLIN | select.EPOLLET)  # 工作在ET模式
                                # conn_sock.settimeout(self.__timeouts)
                                # 当前链接进入队列
                                self.__client_connections[conn_fileno] = conn_sock
                                # 当前链接IP进入队列
                                self.__client_ip[conn_fileno] = client_ip
                                # 当前连接接受信息
                                self.__client_requests[conn_fileno] = b""
                                # 记录访问日志
                                # Log.access("host: %s, port: %s" % (client_ip, client_port))
                        except socket.error as e:
                            # print(dir(e))
                            # errno代码为11(EAGAIN)
                            if e.errno == 11:
                                pass
                    # 当客户端有输入时
                    # 表示对应的文件描述符可以读(包括对端SOCKET正常关闭)
                    elif event & select.EPOLLIN:
                        self.__epollIn(fileno)
                    elif event & select.EPOLLOUT:
                        conn = self.__client_connections[fileno]
                        send_list = self.__send_list
                        # print(send_list)
                        if send_list[0] > 0:
                            self.__socket_parser.send(conn, send_list[0], send_list[1])
                        if send_list[0] <= 0:
                            self.__epoll.modify(fileno, select.EPOLLET)
                            conn.shutdown(socket.SHUT_RDWR)
                        self.__epoll.modify(fileno, select.EPOLLIN)
                    # 表示对应的文件描述符被挂断
                    elif event & select.EPOLLHUP:
                        self.__epoll.unregister(fileno)
                        self.__client_connections[fileno].close()
                        del self.__client_connections[fileno]
        finally:
            self.__epoll.unregister(self.__socket.fileno())
            self.__epoll.close()
            self.__socket.close()

    # 获取处理程序名
    # command 命令号
    def __getHandler(self, command):
        handler_name = "handler_" + str(command)
        handler_list = dir(self.__app)
        if handler_name in handler_list:
            handler_name = "self._Server__app." + handler_name
        else:
            handler_name = ""
        return handler_name

    # 处理输入
    # fileno 文件描述符
    def __epollIn(self, fileno):
        try:
            # 取得当前链接对象
            conn = self.__client_connections[fileno]
            # 取得当前内容
            requests = self.__client_requests[fileno]
            # 取得头信息
            header = self.__socket_parser.getHeader(conn)
            cmd = header["cmd"]
            if cmd == 0:
                self.__epoll_close(fileno)
                return False
            # 获取内容长度
            body_info = self.__socket_parser.getBody(conn, header["body_len"])
            # 获取处理程序
            handler_name = self.__getHandler(cmd)
            if len(handler_name) > 0:
                send_list = eval(handler_name)(body_info)
            else:
                send_list = [0, {"error": "cmd not defined"}]
            self.__send_list = send_list
            # 处理程序的返回值发送回调用者,返回值格式为[标识符, {}]
            # self.__socket_parser.send(conn, send_list[0], send_list[1])
            # 修改文件描述符为可读状态
            self.__epoll.modify(fileno, select.EPOLLOUT)
        except:
            Log.error()
            self.__epoll_close(fileno)
            return False

    # 关闭连接
    def __epoll_close(self, fileno):
        try:
            self.__client_connections[fileno].shutdown(socket.SHUT_RDWR)
        except:
            pass
        finally:
            self.__epoll.unregister(fileno)
            self.__client_connections[fileno].close()
            del self.__client_connections[fileno]
            del self.__client_ip[fileno]
            del self.__client_requests[fileno]
Exemple #5
0
 def __init__(self, app=""):
     self.__app = app
     self.__socket_parser = SocketParser()
Exemple #6
0
class Server():
    
    #白名单列表, 默认允许本机连接
    __allow_ip = ["127.0.0.1"]
    #epoll对象
    __epoll = ""
    #socket链接
    __socket = ""
    #超时时间设置,客户端10秒内没有任何输入,系统会自动断开
    #从第一次有输入后的10秒开始计时,第一次输入的10秒不计时
    #__timeouts = 5 #秒数
    #监听主机IP, 默认监听
    __host = "0.0.0.0"
    #监听主机端口,默认为8888
    __port = 8888
    #等待连接队列的最大长度
    __listens = 1024
    #设置阻塞模式,1阻塞模式 0非阻塞模式, 默认非阻塞模式
    __block = 0
    #连接列表,值为:socket对象
    __client_connections = {}
    #连接IP列表
    __client_ip = {}
    #连接接受信息列表
    __client_requests = {}
    #注册的应用程序
    __app = ""
    #socket解析对象
    __socket_parser = ""
    #发送给client的数据
    __send_list = ""
    
    def __init__(self, app=""):
        self.__app = app
        self.__socket_parser = SocketParser()
        
    #设置白名单,默认运行本机IP
    def setAllowIp(self, ip_list=[]):
        if len(ip_list) > 0:
            for lv in ip_list: self.__allow_ip.append(lv)
    
    #检测IP是否在白名单里
    def __isAllowIp(self, ip):
        if len(self.__allow_ip) == 0:
            return False
        else:
            try:
                #如果存在返回True,否则抛出异常
                self.__allow_ip.index(ip)
                return True
            except:
                return False
    
    #服务监听            
    def listen(self, port=0):
        #创建socket链接
        self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #在绑定前让套接字允许复用(两个套接字可以绑定到同一个端口上)
        self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        #绑定主机和端口
        if port == 0:
            port = self.__port
        self.__socket.bind((self.__host, int(port)))
        #等待连接队列的最大长度
        self.__socket.listen(self.__listens)
        #设置阻塞模式,默认为非阻塞模式
        self.__socket.setblocking(self.__block)
        #创建epoll对象
        self.__epoll = select.epoll()
        self.__epoll.register(self.__socket.fileno(), select.EPOLLIN | select.EPOLLET) #工作在ET模式
        #开始服务
        self.__loop()
        
    #开始服务
    def __loop(self):
        try:
            while True:
                events = self.__epoll.poll(-1)
                #print("polling...")
                #print(events)
                for fileno, event in events:
                    #当请求连接时(处理客户端链接)
                    #只有客户端第一次建立链接时会执行一次
                    if fileno == self.__socket.fileno():
                        try:
                            while True:
                                conn_sock, client_values = self.__socket.accept()
                                #print("accept...")
                                client_ip, client_port = client_values
                                conn_sock.setblocking(0)
                                #检测白名单
                                if not self.__isAllowIp(client_ip):
                                    conn_sock.close() #关闭链接
                                    break
                                conn_fileno = conn_sock.fileno()
                                self.__epoll.register(conn_fileno, select.EPOLLIN | select.EPOLLET) #工作在ET模式
                                #conn_sock.settimeout(self.__timeouts)
                                #当前链接进入队列
                                self.__client_connections[conn_fileno] = conn_sock
                                #当前链接IP进入队列
                                self.__client_ip[conn_fileno] = client_ip
                                #当前连接接受信息
                                self.__client_requests[conn_fileno] = b''
                                #记录访问日志
                                #Log.access("host: %s, port: %s" % (client_ip, client_port))
                        except socket.error as e:
                            #print(dir(e))
                            #errno代码为11(EAGAIN)
                            if e.errno == 11:
                                pass
                    #当客户端有输入时
                    #表示对应的文件描述符可以读(包括对端SOCKET正常关闭)
                    elif event & select.EPOLLIN:
                        self.__epollIn(fileno)
                    elif event & select.EPOLLOUT:
                        conn = self.__client_connections[fileno]
                        send_list = self.__send_list
                        #print(send_list)
                        if send_list[0] > 0:
                            self.__socket_parser.send(conn, send_list[0], send_list[1])
                        if send_list[0] <= 0:
                            self.__epoll.modify(fileno, select.EPOLLET)
                            conn.shutdown(socket.SHUT_RDWR)
                        self.__epoll.modify(fileno, select.EPOLLIN)
                    #表示对应的文件描述符被挂断
                    elif event & select.EPOLLHUP:
                        self.__epoll.unregister(fileno)
                        self.__client_connections[fileno].close()
                        del self.__client_connections[fileno]
        finally:
            self.__epoll.unregister(self.__socket.fileno())
            self.__epoll.close()
            self.__socket.close()
    
    #获取处理程序名
    #command 命令号
    def __getHandler(self, command):
        handler_name = "handler_" + str(command)
        handler_list = dir(self.__app)
        if(handler_name in handler_list):
            handler_name = "self._Server__app." + handler_name
        else:
            handler_name = ""
        return handler_name
        
    #处理输入
    #fileno 文件描述符
    def __epollIn(self, fileno):
        try:
            #取得当前链接对象
            conn = self.__client_connections[fileno]
            #取得当前内容
            requests = self.__client_requests[fileno]
            #取得头信息
            header = self.__socket_parser.getHeader(conn)
            cmd = header['cmd']
            if cmd == 0:
                self.__epoll_close(fileno)
                return False
            #获取内容长度
            body_info = self.__socket_parser.getBody(conn, header['body_len'])
            #获取处理程序
            handler_name = self.__getHandler(cmd)
            if len(handler_name) > 0:
                send_list = eval(handler_name)(body_info)
            else:
                send_list = [0,{"error":"cmd not defined"}]
            self.__send_list = send_list
            #处理程序的返回值发送回调用者,返回值格式为[标识符, {}]
            #self.__socket_parser.send(conn, send_list[0], send_list[1])
            #修改文件描述符为可读状态
            self.__epoll.modify(fileno, select.EPOLLOUT)
        except:
            Log.error()
            self.__epoll_close(fileno)
            return False
        
    #关闭连接
    def __epoll_close(self, fileno):
        try:
            self.__client_connections[fileno].shutdown(socket.SHUT_RDWR)
        except:
            pass
        finally:
            self.__epoll.unregister(fileno)
            self.__client_connections[fileno].close()
            del self.__client_connections[fileno]
            del self.__client_ip[fileno]
            del self.__client_requests[fileno]
Exemple #7
0
def getHeader(socket_obj):
    s = SocketParser()
    header = s.getHeader(socket_obj)
    if header['cmd'] == 0:
        return False
    return header
Exemple #8
0
def send(socket_obj, command, body):
    s = SocketParser()
    s.send(socket_obj, command, body)
Exemple #9
0
def getHeader(socket_obj):
    s = SocketParser()
    header = s.getHeader(socket_obj)
    if header['cmd'] == 0:
        return False
    return header
Exemple #10
0
def send(socket_obj, command, body):
    s = SocketParser()
    s.send(socket_obj, command, body)