我最近被介绍到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,使其更有可能打印出连接。
答案 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.