我想创建一个可以在多个端口上运行的python网络应用程序(例如:TCP:1234,TCP:5678等)。
所以我可以说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)
答案 0 :(得分:2)
在多个套接字上进行侦听与在单个套接字上进行侦听没有什么不同。
您已经需要以某种方式处理侦听器套接字和所有客户端连接套接字。您可以通过以下方式执行此操作:
select.select
(或poll
,kqueue
,epoll
等创建循环。)asyncore
。几乎所有这些方案都可以用于处理多个侦听器。最简单的方法是将两者合并为一个(例如,一个select
循环,它处理所有的侦听器及其所有客户端套接字,或者为每个侦听器和客户端套接字分别使用一个线程。) p>
出于性能或调试原因,您可能希望改为使用双层混合方法(例如,每个侦听器的一个线程,每个侦听器的所有客户端套接字都有一个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')
如果您认为自己永远不需要同时处理两个客户......那么,您可能错了,但是......您可以使用上述大部分技术,而且可能会稍微简单一些。例如,您可以选择侦听器,然后在返回循环之前同步执行accept和client-socket通信。或者,您可以为每个侦听器创建进程或线程,但在每个侦听器中同步处理accept和client-socket通信。等等。
http://pastebin.com/wLVLT49i显示了一个简单的示例,似乎是您尝试做的事情。由于它为每个套接字使用一个进程(通过os.fork
),它允许在不同端口上同时连接;因为它不会在每个进程内异步执行任何操作,所以它不允许同时连接到同一个端口。 (当然它是特定于POSIX的,因为它使用fork
。)
如果您想首先学习如何编写异步网络服务器,我建议您执行两种不同的实现:select
和线程。它们在概念上是基础的,而且相对容易编码。
首先,对于select
,您必须了解事件循环的想法 - 事件是每个新的传入连接,现有连接上的每个传入网络数据包,即使每次都是管道写作取消畅通。这里的棘手问题是,与任何事件循环一样,您需要处理每个事件并在不阻塞的情况下返回,并且不需要花费太多CPU时间。例如,对于echo服务器,您不能只对其他套接字执行写操作,因为其中一些可能很忙。所以相反,你必须将输出粘贴在每个套接字的写缓冲区中,并且当它们准备就绪时,它们将在以后的某个事件循环中运行它。
同时,对于线程,每个连接的一个单独的线程似乎使一切变得微不足道,但是当你需要将消息从一个线程回显到另一个线程时会发生什么?您需要某种形式的线程间通信,或者需要具有线程间同步的共享数据。因此,您可能在每个套接字上都有Queue
的写入,因此任何其他套接字的线程都可以将消息推送到队列中。
这些都不如转化良好的反应堆或反应器能做的那么好,但它值得学习基础知识 - 特别是因为你将面临阻塞问题(来自select
)和任何解决方案的通信问题(来自线程),当你在更高层次上工作时,它们会变得更加神秘和难以调试。