python - 为什么我会看到 'connection reset by peer' 错误?

标签 python sockets network-programming system

我正在测试 cogen在使用 python 2.6.1 的 Mac OS X 10.5 机器上。我有一个简单的回显服务器和客户端泵,可以创建 10,000 个客户端连接作为测试。 1000、5000 等都非常出色。然而,在大约 10,000 个连接时,服务器开始丢弃随机客户端 - 客户端看到“连接被对等方重置”。

我是否缺少一些基本的网络背景知识?

请注意,我的系统配置为处理打开的文件(launchctl limit、sysctl(maxfiles 等)和 ulimit -n 都是有效的;在那里,完成了)。此外,我已经证实 cogen 正在选择在幕后使用 kqueue。

如果我向 client-connect() 调用添加轻微的延迟,一切都会很好。因此,我的问题是,为什么在短时间内连接频率很高的情况下,服务器承受压力会丢弃其他客户端?还有其他人遇到过这个吗?

为了完整起见,这是我的代码。

这是服务器:

# echoserver.py

from cogen.core import sockets, schedulers, proactors
from cogen.core.coroutines import coroutine
import sys, socket

port = 1200

@coroutine
def server():
    srv = sockets.Socket()
    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    addr = ('0.0.0.0', port)
    srv.bind(addr)
    srv.listen(64)
    print "Listening on", addr
    while 1:
        conn, addr = yield srv.accept()
        m.add(handler, args=(conn, addr))

client_count = 0

@coroutine
def handler(sock, addr):
    global client_count
    client_count += 1
    print "SERVER: [connect] clients=%d" % client_count
    fh = sock.makefile()
    yield fh.write("WELCOME TO (modified) ECHO SERVER !\r\n")
    yield fh.flush()
    try:
        while 1:
            line = yield fh.readline(1024)
            #print `line`
            if line.strip() == 'exit':
                yield fh.write("GOOD BYE")
                yield fh.close()
                raise sockets.ConnectionClosed('goodbye')
            yield fh.write(line)
            yield fh.flush()
    except sockets.ConnectionClosed:
        pass
    fh.close()
    sock.close()
    client_count -= 1
    print "SERVER: [disconnect] clients=%d" % client_count

m = schedulers.Scheduler()
m.add(server)
m.run()

这是客户端:

# echoc.py

import sys, os, traceback, socket, time
from cogen.common import *
from cogen.core import sockets

port, conn_count = 1200, 10000
clients = 0

@coroutine
def client(num):
    sock = sockets.Socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    reader = None
    try:
        try:
            # remove this sleep and we start to see 
            # 'connection reset by peer' errors
            time.sleep(0.001)
            yield sock.connect(("127.0.0.1", port))
        except Exception:
            print 'Error in client # ', num
            traceback.print_exc()
            return
        global clients
        clients += 1
        print "CLIENT #=%d [connect] clients=%d" % (num,clients)
        reader = sock.makefile('r')
        while 1:
            line = yield reader.readline(1024)
    except sockets.ConnectionClosed:
        pass
    except:
        print "CLIENT #=%d got some other error" % num
    finally:
        if reader: reader.close()
        sock.close()
        clients -= 1
        print "CLIENT #=%d [disconnect] clients=%d" % (num,clients)

m = Scheduler()
for i in range(0, conn_count):
    m.add(client, args=(i,))
m.run()

感谢您提供任何信息!

最佳答案

Python 的套接字 I/O 有时会受到对等方重置连接的影响。它与全局解释器锁以及线程的调度方式有关。我 blogged有关该主题的一些引用资料。

time.sleep(0.0001) 似乎是推荐的解决方案,因为它调整线程调度并允许套接字 I/O 完成。

关于python - 为什么我会看到 'connection reset by peer' 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/441374/

相关文章:

python - 在 python 列表理解中打印(或执行语句)

c# - 在没有客户端请求的情况下在客户端套接字上发送数据

node.js - 是否可以从 socket.io-emitter 广播

java - InetSocketAddress 与 InetAddress

java - 尝试从套接字读取时出现非法阻塞模式异常

javascript - Node.js UDP 网络多播

python - 如何使用 pip 搜索可用的 Python 包?

python - networkx 中的 nx.get_node_attributes 返回一个空字典

python - 从 Python 运行 Perl 脚本并将输出写入文件时,为什么文件是空的?

java - 在java中通过客户端服务器网络将进程输出打印到JTextArea