Python 一次做更多的迭代

Python 一次做更多的迭代,python,for-loop,Python,For Loop,我有一个阻塞for循环,我试图用套接字连接到服务器。 我想做一个非阻塞循环,因为它需要很多时间,比如重叠连接。 下面是我的示例代码: import socket for _ in range(100): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsocko

我有一个阻塞for循环,我试图用套接字连接到服务器。 我想做一个非阻塞循环,因为它需要很多时间,比如重叠连接。
下面是我的示例代码:

import socket

for _ in range(100):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
        s.connect(('', 4444))

正如MLAlex所建议的,使用asyncio库是有意义的

这是从以下方面得到启发的:

e、 g.与此回送服务器连接(回送一条消息需要三秒):

产生:

Send: 'msg 0'
Send: 'msg 1'
Send: 'msg 2'
Send: 'msg 3'
Send: 'msg 4'
Send: 'msg 5'
Send: 'msg 6'
Send: 'msg 7'
Send: 'msg 8'
Send: 'msg 9'
Received: 'msg 0'
Close the connection
Received: 'msg 1'
Close the connection
Received: 'msg 2'
Close the connection
Received: 'msg 3'
Close the connection
Received: 'msg 4'
Close the connection
Received: 'msg 5'
Close the connection
Received: 'msg 6'
Close the connection
Received: 'msg 7'
Close the connection
Received: 'msg 8'
Close the connection
Received: 'msg 9'
Close the connection
['msg 0', 'msg 1', 'msg 2', 'msg 3', 'msg 4', 'msg 5', 'msg 6', 'msg 7', 'msg 8', 'msg 9']
在三秒左右,即仅满足一个请求所需的时间

real    0m3,169s
user    0m0,044s
sys     0m0,084s
如果我们在服务器回复所需的时间上引入一些差异,我们可以看到客户端接收结果的顺序不正确。 e、 g.第10行:

await asyncio.sleep(randint(3,4))
然后,客户端的输出变为:

(tih1) SO $ time python aio_cnx.py 
Send: 'msg 0'
Send: 'msg 1'
Send: 'msg 2'
Send: 'msg 3'
Send: 'msg 4'
Send: 'msg 5'
Send: 'msg 6'
Send: 'msg 7'
Send: 'msg 8'
Send: 'msg 9'
Received: 'msg 1'
Close the connection
Received: 'msg 2'
Close the connection
Received: 'msg 3'
Close the connection
Received: 'msg 7'
Close the connection
Received: 'msg 8'
Close the connection
Received: 'msg 9'
Close the connection
Received: 'msg 0'
Close the connection
Received: 'msg 4'
Close the connection
Received: 'msg 5'
Close the connection
Received: 'msg 6'
Close the connection
['msg 0', 'msg 1', 'msg 2', 'msg 3', 'msg 4', 'msg 5', 'msg 6', 'msg 7', 'msg 8', 'msg 9']

real    0m4,135s
user    0m0,059s
sys     0m0,013s

基于您尝试在套接字上执行非块I/O的事实,尝试使用选择器

我的示例代码用于在本地主机ssh服务器上运行 有10次并发连接尝试

import sys
import socket
import selectors

sel = selectors.EpollSelector()

def read_conn(obj, mask):
    try:
        data = obj.recv(1024)
        if data :
            print(data.decode("utf-8"))
        else:
            sel.unregister(obj)
            obj.close()
    except Exception as  ex:
        print( ex )
        sel.unregister(obj)
        obj.close()


def write_conn(obj, mask):
    msg=b"flooding\n\n"
    obj.send(msg)
    sel.unregister(obj)
    sel.register(obj,selectors.EVENT_READ,read_conn)
    return

for i in range(10) :

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    addr = ('127.0.0.1',22)
    try:
        sock.connect(addr)
        print(f"tried {i}")
        sock.setblocking(False)
        sel.register(sock,selectors.EVENT_WRITE, write_conn)
    except socket.error as ex:
        print("fail to connect error {}".format(ex))
        sys.exit(1)

while True:
    events = sel.select(1)
    if len(events) == 0:
        print("all done")
        break
    for key, mask in events:
        callback= key.data
        callback(key.fileobj,mask)
在我的虚拟机上显示它的输出

tried 0
tried 1
tried 2
tried 3
tried 4
tried 5
tried 6
tried 7
tried 8
tried 9
SSH-2.0-OpenSSH_7.4
Protocol mismatch.

SSH-2.0-OpenSSH_7.4
Protocol mismatch.

SSH-2.0-OpenSSH_7.4
Protocol mismatch.

[Errno 104] Connection reset by peer
[Errno 104] Connection reset by peer
[Errno 104] Connection reset by peer
SSH-2.0-OpenSSH_7.4
Protocol mismatch.

  cut out duplicate outputs

all done

你要找的是多线程。看看异步IO的I/O操作如果你在浏览器中搜索“Python多处理”,你会找到比我们在这里管理的更好的参考资料。我知道线程、多处理和异步IO,但如果可以的话,我需要一个代码示例。谢谢你,阿加尼真的很感谢你的评论和代码,但我的代码比我在问题中给出的示例更复杂,你的代码永远不会与我的代码一起工作。对不起,我明白了。没问题,根据提供的信息,这是一种方法。如果它不符合您的限制,它可能会帮助其他人作为答案是的,这是因为我不想使我的代码繁重或完全打乱它。很抱歉,againi在socket.connect()之后进行了非块设置,因为connect()在非块模式下很容易引发异常,错误号115如果要进行非块连接,请将sock.connect()调用替换为sock.connect_ex()并将sock.setblocking()移到sock.connect_ex()之前,另请参见
import sys
import socket
import selectors

sel = selectors.EpollSelector()

def read_conn(obj, mask):
    try:
        data = obj.recv(1024)
        if data :
            print(data.decode("utf-8"))
        else:
            sel.unregister(obj)
            obj.close()
    except Exception as  ex:
        print( ex )
        sel.unregister(obj)
        obj.close()


def write_conn(obj, mask):
    msg=b"flooding\n\n"
    obj.send(msg)
    sel.unregister(obj)
    sel.register(obj,selectors.EVENT_READ,read_conn)
    return

for i in range(10) :

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    addr = ('127.0.0.1',22)
    try:
        sock.connect(addr)
        print(f"tried {i}")
        sock.setblocking(False)
        sel.register(sock,selectors.EVENT_WRITE, write_conn)
    except socket.error as ex:
        print("fail to connect error {}".format(ex))
        sys.exit(1)

while True:
    events = sel.select(1)
    if len(events) == 0:
        print("all done")
        break
    for key, mask in events:
        callback= key.data
        callback(key.fileobj,mask)
tried 0
tried 1
tried 2
tried 3
tried 4
tried 5
tried 6
tried 7
tried 8
tried 9
SSH-2.0-OpenSSH_7.4
Protocol mismatch.

SSH-2.0-OpenSSH_7.4
Protocol mismatch.

SSH-2.0-OpenSSH_7.4
Protocol mismatch.

[Errno 104] Connection reset by peer
[Errno 104] Connection reset by peer
[Errno 104] Connection reset by peer
SSH-2.0-OpenSSH_7.4
Protocol mismatch.

  cut out duplicate outputs

all done