Java中的多线程FTP服务器
我正在用Java制作一个多线程FTP服务器,我有一个关于处理多个客户端的问题。现在,我有一个如下所示的服务器:Java中的多线程FTP服务器,java,multithreading,Java,Multithreading,我正在用Java制作一个多线程FTP服务器,我有一个关于处理多个客户端的问题。现在,我有一个如下所示的服务器: public class Server { private static final int HOST_PORT = 6000; private ServerSocket serverSocket; public Server(ServerModel serverModel) throws IOException { serverSocket = new ServerSoc
public class Server {
private static final int HOST_PORT = 6000;
private ServerSocket serverSocket;
public Server(ServerModel serverModel) throws IOException {
serverSocket = new ServerSocket(HOST_PORT);
}
public void start() {
try {
acceptClients();
} catch (IOException e) {
e.printStackTrace();
}
}
private void acceptClients() throws IOException {
while (true) {
Socket client = serverSocket.accept();
ServerModel serverModel = new ServerModel();
Thread worker = new Thread(new ServerWorker(client, serverModel));
worker.start();
}
}
}
以及一个ServerWorker对象,负责解释客户端命令并响应它们:
public class ServerWorker implements Runnable {
private ServerRemoteHandler serverRemoteHandler;
private ServerModel serverModel;
private static final int GET_CODE = 1;
private static final int PUSH_CODE = 2;
private static final int CHANGE_DIRECTORY_CODE = 3;
private static final int PRINT_WORKING_DIRECTORY_CODE = 4;
private static final int FILE_EXISTS_CODE = 5;
private static final int LIST_FILES_DIRECTORIES_CODE = 6;
private static final int EXIT_CODE = 0;
public ServerWorker(Socket client, ServerModel serverModel) throws IOException {
this.serverModel = serverModel;
try {
serverRemoteHandler = new ServerRemoteHandler(client);
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseCommand() {
int command;
try {
while (true) {
command = serverRemoteHandler.getCommand();
switch (command) {
case CHANGE_DIRECTORY_CODE:
changeDirectory();
break;
case PRINT_WORKING_DIRECTORY_CODE:
printWorkingDirectory();
break;
case FILE_EXISTS_CODE:
fileExists();
break;
case LIST_FILES_DIRECTORIES_CODE:
listFilesDirectories();
break;
case GET_CODE:
pushFile();
break;
case PUSH_CODE:
getFile();
break;
case EXIT_CODE:
exit();
break;
}
}
} catch (IOException e) {
exit();
}
}
private void printWorkingDirectory() throws IOException {
serverRemoteHandler.printWorkingDirectory(serverModel.getCurrentPath());
}
private void changeDirectory() throws IOException {
String fileName = serverRemoteHandler.getFileName();
boolean success = serverModel.changeDirectory(fileName);
serverRemoteHandler.changeDirectory(success);
}
private void fileExists() throws IOException {
String fileName = serverRemoteHandler.getFileName();
serverRemoteHandler.fileExists(serverModel.fileExists(fileName));
}
private void pushFile() throws IOException {
File file = serverModel.getFile(serverRemoteHandler.getFileName());
long fileSize = serverModel.getFileSize(file);
serverRemoteHandler.pushFile(file, fileSize);
}
private void listFilesDirectories() throws IOException {
serverRemoteHandler.listFilesDirectories(serverModel.listFilesDirectories());
}
private void getFile() throws IOException {
String fileName = serverRemoteHandler.getFileName();
File file = new File(serverModel.getCurrentPath() + File.separator + fileName);
serverRemoteHandler.getFile(file);
}
private void exit() {
serverRemoteHandler.exit();
}
@Override
public void run() {
while (true) {
parseCommand();
}
}
}
每个ServerWorker都有一个名为RemoteHandler的对象,其任务是从流发送和接收信息。我的问题是关于这一行:
Thread worker = new Thread(new ServerWorker(client, serverModel));
这个线安全吗?这是一种很好的实施方式吗?谢谢。是的,它是线程安全的。该行中的所有内容都是方法本地的,因此它只能由当前线程访问,然后工作线程启动,而这个线程循环并获取这些变量的一组新值
(当然,这并不意味着整个程序都是线程安全的。)太好了,非常感谢。我还有一个问题。既然每个线程都获得了一个新的可运行对象,那么由于没有共享变量,它本身就不是线程安全的吗?@namarino41这是正确的。避免共享变量,避免线程安全问题。这当然包括
静态变量。这就是我的想法。非常感谢您的帮助,非常感谢。同意,方法本地将在堆栈中,只要serverSocket类(不是方法本地)之间不共享任何内容。祝你好运:)@amitmah方法局部变量在堆栈上,句号。其余的都与此无关。这个问题已经回答了。你只是在制造混乱。你真的需要ServerWorker、ServerModel、
和ServerRemoteHandler
三者吗?对我来说似乎有点过分了。该模型实际上只是一个返回文件信息的实用程序类。远程处理程序将所有网络交互抽象出来,服务器工作者实现runnable。你建议用不同的方式做吗?不建议。我可能会做得更简单一些,但你说的话听起来很合理。我知道这不是为了讨论,只是出于好奇,你会怎么做?总是想知道如何更好地设计这些东西。只要快速浏览上面的内容,我可能根本没有ServerRemoteHandler
,而且我肯定会将所有文件系统的东西,如changeDirectory()
放入ServerModel
,我可能会将其重命名为远程文件系统客户端视图。但我从来都不是MVC的粉丝。