【问题标题】:Twisted Socket Send Message ImmediatelyTwisted Socket 立即发送消息
【发布时间】:2012-05-22 03:00:09
【问题描述】:

我正在制作一个与 Twisted 套接字通信的 iPhone 应用程序,当我要发送一条消息时它工作得很好。但是,我的问题是我需要向应用程序发送许多不同的信息。这是我的代码。

            if numrows == 1:
                #Did login
                msg = "%s: Login Credentials Success" % _UDID
                print msg
                for c in self.factory.clients:
                    c.message(msg)
                    time.sleep(0.5)

                for result in results:
                    for i in range(1, 6):
                        msg = "%s:L%d;%s" % (_UDID, i, result[i])
                        print msg
                        for c in self.factory.clients:
                            c.message(msg)
                            time.sleep(0.5)
            else:
                msg = "%s: Login Credentials Failed" % _UDID
                print msg
                for c in self.factory.clients:
                    c.message(msg)
                    time.sleep(0.5)

            cursor.close()
            database.close()

        #print msg

        #for c in self.factory.clients:
            #c.message(msg)

def message(self, message):
    self.transport.write(message)

假设我只发送第一个 msg,并且所有其他 msg 都不存在连同 print 和每个 msg 下面的方法,消息登录凭据成功将被发送到应用程序。但是,如果像您看到的那样放入其余部分,则不会发生任何事情,因为它会一次发送所有内容,即使在代码中添加 time.sleep 也是如此。

应用每 0.05 秒或更短时间检查一次响应。即使登录凭据在顶部,它也不会通过,因为之后会发送更多信息,但是如果没有凭据消息之后的所有信息,它也会通过。

我很想找到这个问题的答案。我已经尝试了我能想到的一切。应用程序不是问题,是 Python。

谢谢。

【问题讨论】:

  • 不要在 Twisted reactor 线程中使用 time.sleep(或任何阻塞函数)。
  • @Jean-PaulCalderone 我用它来测试它,但它不起作用。我发布后发现不使用 time.sleep()。

标签: python twisted


【解决方案1】:

冒着自相矛盾的冒犯风险,您可能需要重新检查您的应用不是问题的说法。听起来您希望完全控制每个传出 TCP 数据包的内容,并且您的应用依赖数据包边界来确定消息边界。一般来说,这不是一个很好的联网方法。一些网络中介可能会在此过程中拆分(碎片)甚至合并数据包,这会使您的应用程序感到困惑。请记住,TCP 不是数据包协议:它是一种流协议,因此您只能真正保证您发送的八位位组将按顺序接收(如果有的话)。

处理不同大小的消息的一种常用方法是在每条消息前面加上一个 X 位大端大小字段,说明后面的消息有多大。通信的接收端首先读取 X 位,然后读取 'size' 八位位组以获取完整消息(阻塞直到该点,并将任何附加信息留在缓冲区中以供下一个消息处理程序获取)。

我不介意为您的 Twisted 代码提供更多帮助,但很可能它已经正确编写。至少,我建议不要立即尝试使 Twisted 刷新网络写入缓冲区。虽然它可能有助于使您的代码看起来可以正常工作,但它实际上只是隐藏了稍后会出现的问题。

【讨论】:

  • 感谢您不介意帮助我。也许它是我的应用程序,但我强烈地感觉到它是我的 Python。如果你能帮助我,谢谢保罗。
  • 在阅读并理解以上内容后,您是否还有具体问题?
  • 问题是如果我发送一条以“login:”开头的消息,应用程序会读取它。但是,如果我进入 for 循环并登录:然后 for 循环包含更多信息,则应用程序不会显示任何响应。我认为它可能只是打印而不发送消息。
  • 我不清楚您所说的“登录:”或“包含更多信息的 for 循环”究竟是什么意思。也许为您的应用程序的另一端发布一些(简化的)代码会有所帮助?
  • 我无法访问 python 或应用程序,因为它在我的另一台计算机上的另一个城市。套接字向应用程序发送“Login:UDID_HERE;Sucessful”以显示登录成功。它可以正常工作,但是当我添加其他要发送的内容(例如 for 循环)时,即使有时间睡眠,它也不会发送。这个周末我可以给你代码。
【解决方案2】:

您的问题似乎是 Twisted 缓冲了您写入它的数据。

显然,在不重构大量代码的情况下,没有简单的方法可以强制数据自行发送。见Twisted transport.writeUsing Twisted's twisted.web classes, how do I flush my outgoing buffers?

在粘贴之前不知道您的代码是什么样的,根据最后一个链接的接受答案:

  • 定义 wait 函数,就像它在接受的答案中一样
  • 确保你的类继承自http.Request
  • defer.inlineCallbacks装饰你的方法message
  • message 方法上调用write 后添加yield wait(N)(对于您必须测试和确定的N 值)

我没有足够的 Twisted 经验,不知道需要哪些步骤,哪些只是原始答案的代码中的一部分,不适用于您的代码。

尽管如此,重新编写 iPhone 应用程序以接受在单个消息中包含多次写入时发送的消息类型是可能的(并且更容易)。

【讨论】:

  • 我已经检查了这两个页面,但我不知道要编码什么。我不擅长 Python,所以如果你能帮我写代码,不胜感激。
  • @AlecK。如果您“在 Python 中不强”,那么 Twisted 不是要尝试使用的框架。即使对于 Python 非常有经验的人来说,它也很复杂且难以正确。
  • 这是一个非常有用的答案。请注意,您的类不必从 http.Request 继承。等待函数、装饰器和yield语句的定义是必要的。
猜你喜欢
  • 2015-10-27
  • 2015-08-25
  • 2023-01-09
  • 2017-05-31
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
相关资源
最近更新 更多