class Server {
public void main() {
// ...
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
Socket socket = serverSocket.accept();
Thread thread = new Thread(new Session(socket));
thread.start();
}
// ..
}
public static synchronized Session findByUser(String user) {
for (int i = 0; i < sessions.size(); i++) {
Session session = sessions.get(i);
if (session.getUserID().equals(user)) {
return session;
}
}
return null;
}
}
class Session {
public Session(Socket socket) {
attach(socket);
}
public void attach(Socket socket) {
// get socket's input and output streams
// start another thread to handle messaging (if not already started)
}
public void run() {
// ...
// user logs in and if he's got another session opened, attach to it
Session session = Server.findByUser(userId);
if (session != null) {
// close input and output streams
// ...
session.attach(socket);
return;
}
// ..
}
}
我在这里的问题是:是否安全发布在Server.findByUser方法会话引用,没有按它是否违反OOP风格等? 或者我应该通过一些不可变的id引用会话并封装整个事情?你还会在这里改变什么?
String sessionId = Server.findByUser(userId);
if (sessionId != null && sessionId.length() > 0) {
// close input and output streams
// ...
Server.attach(sessionId, socket);
return;
}
托马斯:
谢谢您的回答。
我同意,在现实世界,这将是创造Session一个新的实例时使用依赖注入是一个好主意,但随后可能还与接口,右侧(下面的代码)?尽管我可能应该为此进行单元测试,但让我们考虑一下。然后我需要一个Server实例。 那么使用静态方法而不是单数的方式会是一个巨大的OO犯罪吗?
interface Server {
Session findByUser(String user);
}
class ServerImpl implements Server {
public Session findByUser(String user) { }
}
class Session {
public Session(Server server, Socket socket) { }
}
在attach(...)方法好一点 - 我从来没有考虑子类Session类,这可能就是我还没有想过如何risy它可能是调用构造函数公共方法。但是,我实际上需要一些公共方法来将会话附加到不同的套接字,所以也许有一对方法?
class Session {
public Session(Socket socket) {
attach_socket(socket);
}
public void attach(Socket socket) {
attach_socket(socket);
}
private void attach_socket(Socket socket) {
// ...
}
}
这是真的,会议允许客户端调用attach(...)看起来不正确。这可能只是服务器应该访问的那些严重的方法之一。但是如果没有C++的友谊关系,我该怎么做?不知何故,内心课程出现在我的脑海里,但我没有多少考虑,所以这可能是一个完全错误的路径。
每次我收到一个新的连接,我产生一个新的线程(并创建一个新的与它关联的会话实例)来处理传输。这样,当用户发送登录命令时,服务器已准备好接受新的连接。一旦用户的身份通过验证,我会检查他是否有机会登录(还有另一个正在进行的会话)。如果他是我从它的套接字分离onging会话,关闭该套接字,将正在进行的会话连接到当前套接字并关闭当前会话。希望这更清楚地解释实际发生了什么?也许使用会话在这里有点不幸。我真正拥有的是为每个连接(和3个线程)创建的4个不同对象:套接字处理程序,消息发送者,消息接收者和会话(如果这是一个很好的解决方案,这是一个不同的问题......)。我只是简单地尝试了源代码来关注这个问题。
我完全同意,当你可以使用地图时迭代会话列表是没有意义的。但是恐怕这可能是我正在处理的代码中的一个小问题(相信我)。我应该提到它实际上是一些遗留系统,毫不奇怪,最近有人发现它有一些并发性和性能问题。我的任务是修复它......当你几乎只有多线程的理论知识或仅仅用它来显示进度条时,这不是一件容易的事情。
如果在此之后,相当冗长,澄清你对这个架构有更多的了解,我会乐于倾听。
2009-11-27
lukem00
+1
static:使用static可以确定(在一个类中)可以“实例化”多少个“实例”:一个。这确实限制了课程的可用性。 (例如,您不能听另一个套接字。)测试会话实际上是不可能的。 (你不能创建服务器模拟。)这是DI(和服务定位器)的动机。 –
2009-11-27 14:25:08
+0
attach(...):你可以把它封装成private:public void attach(Socket socket) - > void attach(Socket socket)。但我仍然认为责任应该放入服务器。 –
2009-11-27 14:26:05