【问题标题】:Multi Port Network Application多端口网络应用
【发布时间】:2012-10-19 06:26:39
【问题描述】:

我想创建一个可以在多个端口(例如:TCP:1234、TCP:5678 等)上运行的 python 网络应用程序。

所以我可以说 n 个套接字,每个套接字都侦听一个客户端连接。我编写了一个简单的网络应用程序,它侦听一系列端口,但是当我运行该应用程序时,它卡在了第一个套接字进程的侦听阶段!

如何在运行时制作我的单个 python 程序以侦听 N 个端口并且每个端口都等待客户端连接到它。所有套接字都在同时运行和侦听。

Socket/Process #1: Listening on TCP Port 5000
Socket/Process #2: Listening on TCP Port 5001
Socket/Process #3: Listening on TCP Port 5002
...
Socket/Process #N: Listening on TCP Port 6000

欣赏任何想法。

#!/usr/bin/env  python

import socket

def getPortList():
    ports=[]
    nPort=int(raw_input("# how many ports you want? "))
    j = 0
    for i in range(0,nPort):
        ports.append(int(raw_input("Enter port number: ")))
        j+=1
    return ports

def myTCPSocket(port=5000):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
    s.bind(("", int(port)))
    print ("\nWaiting for connections!\n")
    s.listen(5)
    (clientsock, clientaddr) = s.accept()
    print(clientaddr)

    data = "start"

    while len(data):
                clientsock.send("\nWelcome to Echo Server\n")
                data = clientsock.recv(1024)
                print ("Data sent is: ", data)
                clientsock.send(data)
                if data == "exit\r\n":
                        clientsock.close()

plst = getPortList()

for item in plst:
    myTCPSocket(item)

【问题讨论】:

  • 你如何处理同一个套接字上的多个连接?一个显式的select 循环、asyncore、一个更高级别的反应器或像 Twisted 这样的前摄器、每个连接的线程、每个连接的进程……?无论您为此做什么,也适用于多个侦听器套接字。您的输出意味着您为每个侦听器都有一个单独的进程,这应该可以工作。你能告诉我们“卡住”的代码吗?
  • 目前我没有为同一个套接字启用任何多个连接。只有一个客户端可以连接到套接字。它现在很好。问题在于运行 python 程序并让它为每个端口分叉或创建一个套接字/进程,以便客户端可以连接到它。
  • 你真的会更好地设计多个客户端连接,此时这个问题变得微不足道。但是,如果您真的想在没有那个问题的情况下解决这个问题,那么每个套接字的分叉(或者,更好的是,使用multiprocessing)应该可以正常工作。再说一遍,你试过什么没用?
  • 对不起,我无法在这里添加所有代码,我在这里添加了它:link
  • 好吧,您有一个名为 myTCPSocket 的函数,它接受一个客户端并且在客户端离开之前不会返回。然后每个套接字调用一次此函数。所以它将等待端口 5000 上的客户端连接、执行操作并离开;然后等待端口 5001 上的客户端连接,执行操作,然后离开;等等。所有代码都是同步的,除非你做一些事情使它异步(多线程、多处理、事件循环等)。请参阅我的两个示例以了解两种不同的执行方式。

标签: python sockets networking process


【解决方案1】:

侦听多个套接字与侦听单个套接字实际上没有什么不同。

您已经需要以某种方式处理侦听器套接字和所有客户端连接套接字。你可以这样做:

  • 围绕select.select(或pollkqueueepoll等)编写循环。
  • 使用标准库反应器asyncore
  • 使用第三方反应器或像 Twisted 这样的前摄器。
  • 使用特定于操作系统的功能(例如,通过 PyObjC 使用 Cocoa 运行循环和服务器)。
  • 为每个新连接创建一个线程。
  • 为每个新连接创建一个子进程。

几乎所有这些方案也适用于处理多个侦听器。最简单的做法是将两者合二为一(例如,单个 select 循环处理所有侦听器及其所有客户端套接字,或者为每个侦听器和客户端套接字设置一个单独的线程)。

出于性能或调试原因,您可能希望改用两层混合方法(例如,每个侦听器都有一个线程,每个侦听器的所有客户端套接字都有一个 select 循环,或者每个侦听器都有一个进程,每个客户端套接字都有一个线程)。但是,如果您没有任何充分的理由这样做,请不要增加复杂性。

http://pastebin.com/QebZMKz3 显示了一个简单的单select 实现。这是输出:

$ ./multiserve.py 22222 22223 &
(('127.0.0.1', 22222), ' listening')
(('127.0.0.1', 22223), ' listening')
$ echo 'abc' | nc localhost 22222
(('127.0.0.1', 22222), ' <- ', ('127.0.0.1', 64633))
(('127.0.0.1', 64633), ' <- ', 'abc\n')
(('127.0.0.1', 64633), ' EOF')

如果您认为您实际上永远不需要同时处理两个客户端……好吧,您可能错了,但是……您可以使用上述大多数技术,而且可能稍微简单一些。例如,您可以在侦听器上进行选择,然后在返回循环之前同步进行接受和客户端套接字通信。或者您可以为每个侦听器创建一个进程或线程,但在每个侦听器中同步处理接受和客户端套接字通信。以此类推。

http://pastebin.com/wLVLT49i 显示了一个简单的示例,这似乎是您想要做的。由于它为每个套接字使用一个进程(通过os.fork),它确实允许不同端口上的同时连接;由于它不会在每个进程中异步执行任何操作,因此它不允许同时连接到同一端口。 (当然它是 POSIX 特定的,因为它使用 fork。)

如果您首先想学习如何编写异步网络服务器,我建议您进行两种不同的实现:select 和线程。它们在概念上是基本的,并且相对容易编码。

首先,对于select,您必须了解事件循环的概念——事件是每个新的传入连接、现有连接上的每个传入网络数据包,甚至是每次您正在写入的管道畅通无阻。这里的棘手之处在于,与任何事件循环一样,您需要处理每个事件并在没有阻塞的情况下返回,并且不会花费太多的 CPU 时间。例如,对于回显服务器,您不能只在其他套接字上进行写入,因为其中一些可能很忙。因此,您必须将输出粘贴到每个套接字的写入缓冲区中,当您准备好时,他们将在未来通过事件循环运行时获取它。

同时,对于线程,每个连接都有一个单独的线程似乎让一切变得微不足道,但是当您需要将消息从一个线程回显到另一个线程时会发生什么?您要么需要某种形式的线程间通信,要么需要具有线程间同步的共享数据。因此,您可能有一个 Queue 用于在每个套接字上进行写入,因此任何其他套接字的线程都可以将消息推送到队列中。

这些都不如经过精心改造的反应器或前摄器所能做的那样好,但值得学习基础知识 - 特别是因为您将面临阻塞问题(来自select)和任何解决方案的通信问题(来自线程),当您在更高级别工作时,它们会更加神秘和难以调试。

【讨论】:

  • abarnet,非常感谢您提供的所有帮助。我必须阅读它们并进行一些测试并回复您。除了您的回复之外,您还有其他推荐的资源吗?
  • Google 搜索“Python 选择示例”,您应该会找到一些不错的博文。
  • 我真的不知道该怎么感谢你。你真的让我的生活更轻松了。顺便说一句:我必须将线程标记为已解决吗?或者我可以花一天时间阅读然后回来吗?
  • 我认为您可以先阅读并确保它确实已解决,然后再以这种方式进行标记,因为我不确定您是否可以撤消该标记……
  • 我的帐户有问题,今天解决了。现在我有一个问题:当我对这些服务进行任何端口扫描时,整个程序都会关闭!为什么我不能端口扫描这些服务?还是开放端口?是否有阅读这些 Python 网络问题的好地方?感谢您的帮助,如果没有您的帮助,您将无法完成此步骤。
猜你喜欢
  • 1970-01-01
  • 2014-06-14
  • 2014-11-11
  • 2015-07-19
  • 1970-01-01
  • 2016-02-26
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多