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()