多线程应用程序未正确输出

时间:2017-08-15 10:32:38

标签: python multithreading sockets

我最近被介绍到python中的线程模块,所以我决定玩它,我在端口7000上打开了一个python套接字服务器:

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',7000))
s.listen(1)
c, a = s.accept()

并让我的客户端服务器尝试连接到1到65535的每个端口,直到它在端口7000上建立连接。显然这需要很长时间,所以我多线程它:

import threading
import socket
import sys
host = None
def conn(port):
    try:
        s.connect((host,port))
        print 'Connected'
        sys.exit(1)
    except:
        pass
    global host
host = '127.0.0.1'
for i in range(65535):
    t = threading.Thread(target=conn, args=(i,))
    t.start()

当客户端连接其假设以返回消息“已连接”时。但是在调试时我注意到程序有一些非常奇怪的行为。有时程序会返回它已连接的程序,有时程序将无法输出它已连接到服务器,而只是终止而不打印任何内容。

这显然是线程的一个问题。当我使客户端连接到端口7000时,它只有100%的时间工作。但是,将其穿过所有65535端口会导致客户端有时不打印任何内容。这是什么原因以及如何防止或绕过它。

编辑: 我意识到它尝试连接到较少数量的端口,端口1-10和端口7000,使其更有可能打印出连接。

2 个答案:

答案 0 :(得分:0)

65535是一个巨大的数字。

你可能获得的任何性能提升都会被这么多线程相形见绌。操作系统应为每个线程规划处理器时间,然后在线程之间切换需要时间。在最糟糕的情况下(7k非常糟糕)所有操作系统都是线程切换,两者之间的实际工作很少。 2-8个线程(或每个物理核心只是一个线程)的性能要高得多。

此外,请确保等到线程退出,并且不要使用except: pass消除错误。我打赌,那里发生了很多有趣的事情。至少[有选择地]在某处记录这些例外。

修改即可。使用join以确保所有生成的线程在主线程之前退出。

threads = [threading.Thread(target=conn, args=(i,)) for i in range(8)]
for thread in threads:
    thread.start()

# do whatever

for thread in threads:
    thread.join()

答案 1 :(得分:0)

如果connect()失败,请将套接字的状态视为未指定。便携式应用程序应关闭套接字并创建一个新的套接字以重新连接。

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.connect(('127.0.0.1', 6999))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 61] Connection refused
>>>
>>> s.connect(('127.0.0.1', 7000))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 22] Invalid argument
>>> 
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.connect(('127.0.0.1', 7000))
# Connect success.