与TCPServer维护另一个持久的TCP连接

时间:2019-05-13 11:33:03

标签: python tcp xmpp

我正在使用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 个答案:

答案 0 :(得分:0)

我使用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())