Python:更好的打开多个套接字的方法

1 投票
3 回答
5057 浏览
提问于 2025-04-15 12:47

我有一个程序,用来打开很多个网络连接(也就是“套接字”),并保持这些连接打开,以便对我们的服务器进行压力测试。不过,这个程序有几个问题。我觉得它可以比现在的递归调用更高效,而且它实际上还是一个一个地打开连接,而不是同时打开。我知道有一些工具,比如ab,可能可以模拟我想做的事情,但我希望能增加我的Python知识。我是不是应该把这个程序改写成多线程或者多进程的方式呢?

> #!/usr/bin/env python
> 
> import socket, time, sys
> sys.setrecursionlimit(2000)
> 
> def open_socket(counter):   
>   sockname = "s" + str(counter)   
>   port = counter + 3000   
>   sockname = socket.socket()  
>   sockname.bind(('localhost', port))  
>   sockname.listen(1)   
>   if counter == 2:
>     time.sleep(20)   
>   elif counter > 2:
>     counter = counter -1
>     open_socket(counter)
> 
> open_socket(1500)

3 个回答

0

其实这个已经是多进程了——在调用 open_socket 之前加个睡眠,然后从命令行运行,比如说 500 个这样的进程:

for i in `seq 500`; do ./yourprogram & done

不过你实际上并没有连接到什么东西——看起来你是在设置服务器套接字?如果你需要连接到某个东西,肯定应该用并行处理来测试一下(比如多线程,或者像上面那样运行很多进程,或者使用异步连接)。这个链接值得一读:

2

你可以试试用Twisted来解决这个问题。它可以让Python的网络编程变得简单很多。他们的网站上有一些教程,可以帮助你入门。

不过,用Python来做这个任务可能有点过于复杂了。一个更快的办法是直接打开1500个nc的实例:

for i in {3000..4500};
do
    nc -l -p $i &
done
4

我一直搞不懂为什么要用递归而不是简单的循环。我的猜测是,使用简单的循环时,你会一次又一次地覆盖变量sockname,这样Python的垃圾回收机制就会在你创建下一个socket时关闭之前的那个。解决办法是把它们都存储在一个列表里,这样就能防止Python把它们回收掉:

def open_socket(counter):
  sockets = []
  for i in range(counter):
     s = socket.socket()
     s.bind(('localhost', i+3000))
     s.listen(1)
     sockets.append(s)
  time.sleep(20)

另外注意,你代码中的第一次给sockname赋值是多余的,因为它会被第二次赋值覆盖掉。

撰写回答