与 TCPServer 保持另一个持久的 TCP 连接
Posted
技术标签:
【中文标题】与 TCPServer 保持另一个持久的 TCP 连接【英文标题】:Maintaining another persistent TCP connection with TCPServer 【发布时间】:2019-05-13 11:33:02 【问题描述】:我正在使用 slixmpp 连接到 XMPP 服务器,我需要在提供 HTTP 协议时访问此连接,我试图保持持久连接,而不是为每个 HTTP 请求连接到 XMPP 服务器。我正在使用 TCPServer 来获取 HTTP 的功能。我写了这段代码。
import logging
from slixmpp import ClientXMPP
from slixmpp.exceptions import IqError, IqTimeout
import socketserver
from time import sleep
class EchoBot(ClientXMPP):
def __init__(self, jid, password):
ClientXMPP.__init__(self, jid, password)
self.add_event_handler("session_start", self.session_start)
self.add_event_handler("message", self.message)
def session_start(self, event):
self.send_presence()
self.get_roster()
def message(self, msg):
print(msg)
if msg['type'] in ('chat', 'normal'):
msg.reply("Thanks for sending\n%(body)s" % msg).send()
class MyTCPHandler(socketserver.BaseRequestHandler):
xmpp = EchoBot('xxx@fcm.googleapis.com', 'xyz')
def __init__(self,request, client_address,server):
super().__init__(request, client_address,server)
self.xmpp.connect(address=('fcm-xmpp.googleapis.com',5235),use_ssl=True,disable_starttls=True)
self.xmpp.process(forever=True)
def handle(self):
self.data = self.request.recv(1024).strip()
print(" wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,format='%(levelname)-8s %(message)s')
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
这是第一次。 MyTCPHandler
句柄函数只在第一次工作,第二次,它不返回任何响应。我正在使用telnet localhost 9999
来测试连接。这里可能出了什么问题?有没有更好的方法来实现我正在寻找的结果?
如果我评论这三行 TCPServer 按预期工作。
# xmpp = EchoBot('xxx@fcm.googleapis.com', 'xyz')
def __init__(self,request, client_address,server):
super().__init__(request, client_address,server)
# self.xmpp.connect(address=('fcm-xmpp.googleapis.com',5235),use_ssl=True,disable_starttls=True)
# self.xmpp.process(forever=True)
【问题讨论】:
【参考方案1】:我使用 asyncio 解决了这个问题
import logging
from slixmpp import ClientXMPP
from slixmpp.exceptions import IqError, IqTimeout
import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
log = logging.getLogger(__name__)
import asyncio
import base64
import slixmpp
from aiohttp import web
XMPP = None
class EchoBot(ClientXMPP):
def __init__(self, jid, password):
ClientXMPP.__init__(self, jid, password)
self.connected_future = asyncio.Future()
self.add_event_handler("session_start", self.session_start)
self.add_event_handler("message", self.message)
def session_start(self, event):
self.send_presence()
self.get_roster()
def message(self, msg):
if msg['type'] in ('chat', 'normal'):
msg.reply("Thanks for sending\n%(body)s" % msg).send()
def reset_future(self):
"Reset the future in case of disconnection"
self.connected_future = asyncio.Future()
async def handle(request):
"Handle the HTTP request and block until the vcard is fetched"
err_404 = web.Response(status=404, text='Not found')
print(await request.json())
try:
XMPP.send_raw('<message id="gsgsfssdfds"> <gcm xmlns="google:mobile:data"> "notification": "title": "change","body": "body changed","sound":"default","to" : "efsfdsf","message_id":"flajlfdjlfdklajflda","priority":"high","delivery_receipt_requested":true</gcm></message>')
except Exception as e:
print(e)
log.warning("cannot send message")
return err_404
return web.Response(text="yes")
async def init(loop, host: str, port: str, avatar_prefix: str):
"Initialize the HTTP server"
app = web.Application(loop=loop)
app.router.add_route('POST', '/', handle)
srv = await loop.create_server(app.make_handler(), host, port)
log.info("Server started at http://%s:%s", host, port)
return srv
def main(namespace):
"Start the xmpp client and delegate the main loop to asyncio"
loop = asyncio.get_event_loop()
global XMPP
XMPP = EchoBot('xxx@gcm.googleapis.com', 'ysfafdafdsfa')
XMPP.connect(use_ssl=True,disable_starttls=False)
#XMPP.connect()
loop.run_until_complete(init(loop, namespace.host, namespace.port,
namespace.avatar_prefix))
XMPP.reset_future()
loop.run_until_complete(XMPP.connected_future)
try:
loop.run_forever()
except KeyboardInterrupt:
import sys
def parse_args():
"Parse the command-line arguments"
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('--jid', '-j', dest='jid', default=JID,
help='JID to use for fetching the vcards')
parser.add_argument('--password', '-p', dest='password', default=PASSWORD,
help='Password linked to the JID')
parser.add_argument('--host', dest='host', default=HOST,
help='Host on which the HTTP server will listen')
parser.add_argument('--port', dest='port', default=PORT,
help='Port on which the HTTP server will listen')
parser.add_argument('--avatar_prefix', dest='avatar_prefix',
default=AVATAR_PREFIX,
help='Prefix path for the avatar request')
return parser.parse_args()
HOST = '127.0.0.1'
PORT = 8765
JID = 'changeme@example.com'
PASSWORD = 'changemetoo'
AVATAR_PREFIX = 'avatar/'
if __name__ == "__main__":
print(parse_args())
main(parse_args())
【讨论】:
以上是关于与 TCPServer 保持另一个持久的 TCP 连接的主要内容,如果未能解决你的问题,请参考以下文章