这是问题所在。 我的主要工作是:在TestRequestHandler类中将“s”对象传递给“handle”方法。 我的第一步是:通过“点”方法将“s”对象传递给TestServer类,但是这里我卡住了。如何将“s”对象传递给TestRequestHandler?一些建议?
import threading
import SocketServer
from socket import *
class TestRequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
return
def setup(self):
return SocketServer.BaseRequestHandler.setup(self)
def handle(self):
data = self.request.recv(1024)
if (data):
self.request.send(data)
print data
def finish(self):
return SocketServer.BaseRequestHandler.finish(self)
class TestServer(SocketServer.TCPServer):
def __init__(self, server_address, handler_class=TestRequestHandler):
print "__init__"
SocketServer.TCPServer.__init__(self, server_address, handler_class)
return
def point(self,obj):
self.obj = obj
print "point"
def server_activate(self):
SocketServer.TCPServer.server_activate(self)
return
def serve_forever(self):
print "serve_forever"
while True:
self.handle_request()
return
def handle_request(self):
return SocketServer.TCPServer.handle_request(self)
if __name__ == '__main__':
s = socket(AF_INET, SOCK_STREAM)
address = ('localhost', 6666)
server = TestServer(address, TestRequestHandler)
server.point(s)
t = threading.Thread(target=server.serve_forever())
t.setDaemon(True)
t.start()
答案 0 :(得分:2)
如果我理解正确,我想你或许误解了模块是如何工作的。您已经为要绑定的服务器指定了“localhost:6666”的地址。
当您通过调用serve_forever()启动服务器时,这将导致服务器开始侦听localhost:6666上的套接字。
根据文档,该套接字作为“请求”对象传递给您的RequestHandler。当在套接字上收到数据时,你的'handle'方法应该能够使用记录的套接字API从/向该对象发送/发送。
如果你想进一步抽象,看起来你的RequestHandler可以使用类似文件的对象从StreamRequestHandler和读/写扩展到套接字。
关键是,您无需创建额外的套接字,然后尝试强制您的服务器使用新的套接字。 SocketServer模块的部分价值在于它为您管理套接字的生命周期。
另一方面,如果您想从客户端的角度测试服务器,那么您可能希望创建一个可以读取/写入客户端请求的套接字。但是你永远不会将这个套接字传递给你的服务器。您可能会在一个完全独立的过程中执行此操作,并通过套接字通过IPC测试您的服务器。
根据新信息进行修改
要让服务器A在服务器A接收数据时打开服务器B的套接字,一个解决方案就是从RequestHandler内部打开一个套接字。也就是说,根据您的服务要求,您可能需要解决一些其他设计问题。
例如,您可能希望使用一个简单的连接池,即向服务器B打开几个套接字,服务器A可以像资源一样使用它。 Python中可能已经有一些库可以帮助解决这个问题。
鉴于您当前的设计,您的RequestHandler可以作为成员变量访问服务器,因此您可以执行以下操作:
class TestServer(SocketServer.TCPServer):
def point (self, socketB):
self.socketB = socketB # hold serverB socket
class TestRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
if (data):
self.request.send(data)
print data
self.server.socketB ... # Do whatever with the socketB
但就像我说的那样,你可能更好地拥有某种连接池或管理服务器B套接字的其他对象,这样你的服务器处理程序就可以在处理传入请求时获取/释放套接字。 / p>
这样您就可以更好地处理服务器B断开套接字的情况。您当前的设计无法轻松处理损坏的插座。只是一些想法...
答案 1 :(得分:1)
如果s的值设置一次,而不是重新初始化 - 你可以使它成为一个类变量而不是TestServer的实例变量,然后让处理程序通过处理程序构造函数中的TestServer类方法检索它。
例如:TestServer._mySocket = s
答案 2 :(得分:1)
好的,我的主要任务是这个。构建监听服务器(A-server-localhost,6666),在启动期间将打开与不同服务器(B-server-localhost,7777)的“硬”连接。 当客户向A服务器发送数据时(A服务器)将数据(具有与B服务器的硬连接)发送到B服务器,答案从B服务器接收到A服务器并且应答发送到顾客。 然后:客户发送数据,A服务器接收数据,然后发送到B服务器,答案从B服务器接收数据,A服务器向客户发送数据。 如此圆润。只有当服务器A停止时才会关闭与B服务器的连接。 以上都是做这个的考验。