Python 需要帮助在两个套接字之间创建TCP中继吗

Python 需要帮助在两个套接字之间创建TCP中继吗,python,sockets,asynchronous,asyncore,Python,Sockets,Asynchronous,Asyncore,我有以下情况: SomeServer(S) <-> (C)MyApp(S) <-> (C)User (S) represents a server socket (C) represents a client socket 但是,这不是运行 # if user is attached, send data elif self.user: print 'self.user' self.user.send(data) 所以,服

我有以下情况:

SomeServer(S) <-> (C)MyApp(S) <-> (C)User

(S) represents a server socket
(C) represents a client socket
但是,这不是运行

  # if user is attached, send data
    elif self.user:
        print 'self.user'
        self.user.send(data)
所以,服务器并没有将数据中继给用户。我在整个用户类中添加了print语句,以查看运行的内容,init是唯一的东西handle_read()从不运行


为什么会这样?

代码有点难理解,而且我肯定有一些bug。对于 在handle_read()中的示例中,您将MyAppClient的原始套接字
self.socket
传递给 中继服务器。最终,MyAppClient和RelayConnection都在同一个套接字上工作

而不是试图对我编写的原始代码提出错误修复建议 这是一个示例,它实现了代码的意图,并且更清晰、更容易理解。 我已经测试过它与IMAP服务器通信,它可以工作,但忽略了一些 为简洁起见(错误处理、所有情况下正确的close()处理等)

  • 服务器启动与“someserver”的连接。一旦连接 它启动侦听器
  • 侦听器侦听端口8080,只接受1个连接,创建一个用户, 并将其引用传递给服务器侦听器拒绝所有其他 用户处于活动状态时的客户端连接
  • 用户将所有数据转发到服务器,反之亦然。评论 指示身份验证应插入的位置
资料来源:

import asyncore
import socket

class User(asyncore.dispatcher_with_send):

    def __init__(self, sock, server):
        asyncore.dispatcher_with_send.__init__(self, sock)
        self.server = server

    def handle_read(self):
        data = self.recv(4096)
        # parse User auth protocol here, authenticate, set phase flag, etc.
        # if authenticated, send data to server
        if self.server:
            self.server.send(data)

    def handle_close(self):
        if self.server:
            self.server.close()
        self.close()

class Listener(asyncore.dispatcher_with_send):

    def __init__(self, listener_addr, server):
        asyncore.dispatcher_with_send.__init__(self)
        self.server = server
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(listener_addr)
        self.listen(1)

    def handle_accept(self):
        conn, addr = self.accept()
        # this listener only accepts 1 client. while it is serving 1 client
        # it will reject all other clients.
        if not self.server.user:
            self.server.user = User(conn, self.server)
        else:
            conn.close()

class Server(asyncore.dispatcher_with_send):

    def __init__(self, server_addr, listener_addr):
        asyncore.dispatcher_with_send.__init__(self)
        self.server_addr = server_addr
        self.listener_addr = listener_addr
        self.listener = None
        self.user = None

    def start(self):
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect(self.server_addr)

    def handle_error(self, *n):
        self.close()

    def handle_read(self):
        data = self.recv(4096)
        # parse SomeServer auth protocol here, set phase flag, etc.
        if not self.listener:
            self.listener = Listener(self.listener_addr, self)
        # if user is attached, send data
        elif self.user:
            self.user.send(data)

    def handle_close(self):
        if self.user:
            self.user.server = None
            self.user.close()
            self.user = None
        if self.listener:
            self.listener.close()
            self.listener = None
        self.close()
        self.start()

if __name__ == '__main__':
    app = Server(('someserver', 143), ('localhost', 8080))
    app.start()
    asyncore.loop()

您应该注意,如果遵循它,代码不会破坏SO的代码标记;-)谢谢你的例子!请参阅上面对我文章的编辑。@yonatan当我对您的SomeServer和用户协议不太了解时,很难提供帮助。您能否在连接设置后提供更多关于双方交换消息的信息。例如,当客户端连接到端口8080时,您的服务器是否应该向其发送问候消息?如果是这样的话,Listener.handle\u accept应该在构建user之后执行self.server.user.send(问候\u数据)操作。很抱歉,回复太晚了。你的一艘客轮正是你所缺少的!我不可能要求更好的帮助。您的示例代码是完美的!非常感谢您解决了我两周来一直在苦苦挣扎的问题:D:D@yonatan不客气,我很高兴听到你在进步。:)
  # if user is attached, send data
    elif self.user:
        print 'self.user'
        self.user.send(data)
import asyncore
import socket

class User(asyncore.dispatcher_with_send):

    def __init__(self, sock, server):
        asyncore.dispatcher_with_send.__init__(self, sock)
        self.server = server

    def handle_read(self):
        data = self.recv(4096)
        # parse User auth protocol here, authenticate, set phase flag, etc.
        # if authenticated, send data to server
        if self.server:
            self.server.send(data)

    def handle_close(self):
        if self.server:
            self.server.close()
        self.close()

class Listener(asyncore.dispatcher_with_send):

    def __init__(self, listener_addr, server):
        asyncore.dispatcher_with_send.__init__(self)
        self.server = server
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(listener_addr)
        self.listen(1)

    def handle_accept(self):
        conn, addr = self.accept()
        # this listener only accepts 1 client. while it is serving 1 client
        # it will reject all other clients.
        if not self.server.user:
            self.server.user = User(conn, self.server)
        else:
            conn.close()

class Server(asyncore.dispatcher_with_send):

    def __init__(self, server_addr, listener_addr):
        asyncore.dispatcher_with_send.__init__(self)
        self.server_addr = server_addr
        self.listener_addr = listener_addr
        self.listener = None
        self.user = None

    def start(self):
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect(self.server_addr)

    def handle_error(self, *n):
        self.close()

    def handle_read(self):
        data = self.recv(4096)
        # parse SomeServer auth protocol here, set phase flag, etc.
        if not self.listener:
            self.listener = Listener(self.listener_addr, self)
        # if user is attached, send data
        elif self.user:
            self.user.send(data)

    def handle_close(self):
        if self.user:
            self.user.server = None
            self.user.close()
            self.user = None
        if self.listener:
            self.listener.close()
            self.listener = None
        self.close()
        self.start()

if __name__ == '__main__':
    app = Server(('someserver', 143), ('localhost', 8080))
    app.start()
    asyncore.loop()