This is an example interface on a login script by short links to third party extensions, this class can be seen as a poller, each login request could create such a poller, recovery can also design a pool outside to recover. Entirely up to you how you want to manage. After the initialization method using the start and through the socket to connect the analog http message transmission, after the transmission is completed will wait to receive return. Example obtained by parsing the string json return information, the user may be modified to other ways according to their needs. This example implements asynchronous transmission and asynchronous receiver by use of the registration to the underlying fd. Possible problem: the example connet this step is still blocked, there may be performance issues in the limit. |
# -*- coding: utf-8 -*-
import KBEngine
import Functor
import socket
from KBEDebug import *
import json
class LoginPoller:
def __init__(self, _callback, _host, _page, _port, _overtime = 5):
"""
@param _callback: 数据处理完毕之后调用的外部回调, 注意不可在外部回调中销毁这个LoginPoller自己
@param _host: 主机地址, 可以是域名也可以是ip地址
@param _page: 请求页面
@param _port: 请求端口
@param _overtime: 超时秒数
"""
self._socket = None
self._request_str = ""
self._recv_str = ""
self._recv_data = {}
self._callback = _callback
self._host = _host
self._page = _page
self._port = _port
self._overtime = _overtime
self._registerRead = False
self._registerWrite = False
def start(self, _commitName, _realAccountName, _datas, _param_data, _tid):
"""
@param _commitName, _realAccountName, _datas: 这三个参数来自于requestAccountLogin,记在这个LoginPoller中,
数据请求完毕之后可以从外部重新拿到这些数据
@param _param_data: http请求参数
@param _tid: 可视为这个LoginPoller的Id, 回调时会返回这个id, 便于外部管理
"""
self._commitName = _commitName
self._realAccountName = _realAccountName
self._datas = _datas
self._tid = _tid
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
DEBUG_MSG("self._host: %s, self._port: %d" % (self._host, self._port))
self._socket.connect((self._host, self._port))
self.registerRead()
_rstr = "GET " + self._page + "?" + _param_data + " HTTP/1.1\r\n"
_rstr += "Host: %s\r\n" % self._host
_rstr += "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:43.0) Gecko/20100101 Firefox/43.0\r\n"
_rstr += "Connection: close\r\n"
_rstr += "\r\n"
self._request_str = _rstr.encode()
_sendAll = self.send()
if _sendAll != True:
self.registerWrite()
def stop(self):
self.deregisterRead()
self.deregisterWrite()
if self._socket != None:
self._socket.close()
self._socket = None
def send(self):
_send_lenth = self._socket.send(self._request_str)
self._request_str = self._request_str[_send_lenth:]
if len(self._request_str) == 0:
return True
else:
return False
def checkValidity(self):
# 检查有效性, 超时检查
if self._overtime > 0 and self._socket != None:
self._overtime -= 1
return True
else:
return False
def onWrite(self, fileno):
_sendAll = self.send()
if _sendAll == True:
self.deregisterWrite()
def onRecv(self, fileno):
_data = self._socket.recv(2048)
DEBUG_MSG("onRecv: %s" % _data)
if self.checkRecv(_data) == True:
self.processData()
self.stop()
self._callback(self._tid)
def checkRecv(self, _data):
self._recv_str += _data.decode()
DEBUG_MSG("checkRecv: %s" % self._recv_str)
_count1 = self._recv_str.count('{')
_count2 = self._recv_str.count('}')
if _count1 == _count2 and _count1 > 0:
return True
return False
def processData(self):
"""
处理接收数据
从接收数据中截取json串并解析
"""
_index1 = self._recv_str.find('{')
_index2 = self._recv_str.rfind('}')
_bodyStr = self._recv_str[_index1: _index2 + 1]
DEBUG_MSG("_bodyStr: %s" % _bodyStr)
self._recv_data = json.loads(_bodyStr)
DEBUG_MSG("self._recv_data: %s" % str(self._recv_data))
def getPollerInfos(self):
return self._commitName, self._realAccountName, self._datas, self._recv_data
def registerRead(self):
if self._registerRead == False:
KBEngine.registerReadFileDescriptor(self._socket.fileno(), self.onRecv)
self._registerRead = True
def registerWrite(self):
if self._registerWrite == False:
KBEngine.registerWriteFileDescriptor(self._socket.fileno(), self.onWrite)
self._registerWrite = True
def deregisterRead(self):
if self._registerRead == True:
KBEngine.deregisterReadFileDescriptor(self._socket.fileno())
self._registerRead = False
def deregisterWrite(self):
if self._registerWrite == True:
KBEngine.deregisterWriteFileDescriptor(self._socket.fileno())
self._registerWrite = False