翻译问题
您问题中的许多细节没有意义,所以我将您的问题翻译成:
我有一个在端口 8080 上运行的扭曲的 python独立程序,并且我编写了一个在该服务器上运行的不同的独立程序。我希望这两个程序都在一个端口号上运行。当我尝试对所有程序使用相同的端口时:对两个程序都使用端口8081 。我收到此错误:。由于我是twisted的新手,所以我对这些事情了解不多,也没有关于twisted的适当文档。请有人指导我解决这个错误。twisted.internet.error.CannotListenError: Couldn't listen on any:8081: [Errno 98] Address already in use
Twisted 有很好的文档
你评论说:
[...] 没有关于扭曲的适当文档
这种说法是公然错误的。
Twisted 确实有适当的文档,并且与大多数框架相比,它具有出色的文档。仅举几个高质量文档来源中的几个:
- Dave Peticola 的 (krondo) Twisted Introduction - 对扭曲的优秀而深入的介绍,首先解释了 Twisted 所基于的技术。如果你真的想了解twisted,这个(长)介绍就是开始的地方
- Twisted 的主要网站twistedmatrix.com上的高质量和广泛的文档
- 源本身。Twisted 有很好的评论并且令人惊讶地理解源代码,如果上面的文档没有教你从代码中弄清楚你需要什么。
什么原因导致“地址已在使用中”
正如Bart Friederichs之前回答的那样:
只有一个进程可以侦听某个端口。如果您启动进程 1 以侦听端口 8081,然后在同一端口上启动另一个进程,则会收到此错误。
这是来自 TCP 堆栈的错误,而不是来自 python 或扭曲的错误。
这是跨所有操作系统(或至少所有可以运行 Python 的基于进程的操作系统)的 TCP/IP 堆栈的基本事实。
错误是您的操作系统提醒您,当数据到达 IP 端口时,OS/IP 堆栈被设计为仅转发到一个进程,即在该端口上实现应用程序级协议的进程。当第二个程序尝试重新注册某个其他程序已经注册的端口时,就会发生错误。
一般的解决方法
遇到这样的端口重用问题时,您必须问自己:
- 这两个程序甚至运行相同的应用程序级协议吗?
- 如果它们是相同的协议,该协议是否具有路由以便为任何给定事务识别正确的子程序/例程?
- 这两个程序是否在路由中的不同位置?
如果它们不是相同的协议(IE 一个是 HTTP,另一个是 FTP)或者它们是相同的协议但它是一个没有路由的协议(IE 两个 NTP 实例),那么就没有简单的混合方法它们是因为您试图打破 IP 法则(以及构建应用程序协议实现的方式)。唯一的解决方案是将一个(或两个)协议封装到一个通用协议中,该协议也具有应用程序级路由(IE 将 FTP 封装在 HTTP 内并使用 URI 进行路由)
如果它们是相同的协议,并且该协议提供了每个事务的路由(即 HTTP 事务中的 URI)并且它们不在同一个路由位置,那么有更简单的解决方案,即:
将两个应用程序合并为一个。
如果它们是相同的可路由协议但在不同的位置(IE HTTP 协议,其 URI 用于第一个程序 at/login
和第二个程序 at /addfriend
),那么提取两个程序/进程的路由后逻辑并将它们合并应该是微不足道的集成到一个同时执行这两个功能的程序中
使用重定向器前端程序(由于可用的工具,此解决方案仅使用 HTTP 很容易)。
如果您的 HTTP 协议程序具有到不同位置的路由,但由于某种原因很难将逻辑合并在一起(IE 一个程序是用 Java 编写的,另一个是用 Python 编写的),那么您可以使用像nginx这样的重定向器
在这种情况下使用重定向器的方式是在两个不同的未使用端口(IE 12001、12002)上运行您的两个应用程序,然后在您希望服务打开的端口上运行重定向器,使用配置文件,将通过它们唯一的路由位置重定向到您的两个程序(通过 SF 之类的配置:How to redirect requests to a different domain/url with nginx)
代码示例
以下三个程序说明了将两个程序合并为一个的过程,因此可以从同一端口访问两组逻辑。
两个独立的程序:
如果您运行以下代码,则会在localhost:8081
. 如果您随后将 Web 浏览器指向http://127.0.0.1:8081/blah
blah 页面,则会显示该页面。
#!/usr/bin/python
from twisted.internet import defer, protocol, reactor # the reactor
from twisted.web.server import Site # make the webserver go
from twisted.web.resource import Resource
class BlahPage(Resource):
idLeaf = True
def render_GET(self, request):
return "<html><body>Blah Page!</body></html>"
class ShutdownPage(Resource):
def render_GET(self, request):
reactor.stop()
webroot = Resource()
webroot.putChild("blah", BlahPage())
webroot.putChild("shutdown", ShutdownPage())
def main():
# Register the webserver (TCP server) into twisted
webfactory = Site(webroot)
reactor.listenTCP(8081, webfactory)
print ("Starting server")
reactor.run()
if __name__ == '__main__':
main()
此代码将在localhost:8082
. 如果您随后将 Web 浏览器指向http://127.0.0.1:8082/foo
foo 页面,则会显示该页面。
#!/usr/bin/python
from twisted.internet import defer, protocol, reactor # the reactor
from twisted.web.server import Site # make the webserver go
from twisted.web.resource import Resource
class FooPage(Resource):
idLeaf = True
def render_GET(self, request):
return "<html><body>Foo Page!</body></html>"
class ShutdownPage(Resource):
def render_GET(self, request):
reactor.stop()
webroot = Resource()
webroot.putChild("foo", FooPage())
webroot.putChild("shutdown", ShutdownPage())
def main():
# Register the webserver (TCP server) into twisted
webfactory = Site(webroot)
reactor.listenTCP(8082, webfactory)
print ("Starting server")
reactor.run()
if __name__ == '__main__':
main()
合并逻辑
这段代码是前面两个程序的合并,正如你所见,它只需要复制少量代码即可将上述两个程序粘合到一个允许访问http://127.0.0.1:8080/blah
和http://127.0.0.1:8080/blah
.
#!/usr/bin/python
from twisted.internet import defer, protocol, reactor # the reactor
from twisted.web.server import Site # make the webserver go
from twisted.web.resource import Resource
class BlahPage(Resource):
idLeaf = True
def render_GET(self, request):
return "<html><body>Blah Page!</body></html>"
class FooPage(Resource):
idLeaf = True
def render_GET(self, request):
return "<html><body>Foo Page!</body></html>"
class ShutdownPage(Resource):
def render_GET(self, request):
reactor.stop()
webroot = Resource()
webroot.putChild("foo", FooPage())
webroot.putChild("blah", BlahPage())
webroot.putChild("shutdown", ShutdownPage())
def main():
# Register the webserver (TCP server) into twisted
webfactory = Site(webroot)
reactor.listenTCP(8080, webfactory)
print ("Starting server")
reactor.run()
if __name__ == '__main__':
main()