自己動手建立FTP伺服器

前面瞭解了FTP的各項指令及狀態碼,就能夠依照FTP指令的內容來建立FTP Server程式。在標準的FTP Server軟體規格中,明顯有完整的方法解決檔案系統中的各種需求。為了能快速取得學習成果,此範例以被動模式並去除部份指令來得到入門實作的體驗。




Server

啟動FTP Server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package ftp;
 
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
 
//FTP Server
public class Server {
        private int controlPort = 8888; //接收指令埠
        private ServerSocket welcomeSocket;
        boolean serverRunning = true;
         
        //啟動FTP Server
        public static void main(String[] args) {
                new Server();
        }
 
        public Server() {
                try {
                        welcomeSocket = new ServerSocket(controlPort);
                } catch (IOException e) {
                        System.out.println("無法建立網路服務");
                        System.exit(-1);
                }
                System.out.println("FTP服務建立在 " + controlPort);
                int noOfThreads = 0;
                while (serverRunning) {
                        try {
                                Socket client = welcomeSocket.accept();
                                //循序遞增連接埠給新連線傳輸檔案
                                int dataPort = controlPort + noOfThreads + 1;
                                Worker w = new Worker(client, dataPort);
                                System.out.println("收到請求建立連線");
                                noOfThreads++;
                                w.start();
                        } catch (IOException e) {
                                System.out.println("收到請求但連線失敗");
                                e.printStackTrace();
                        }
                }
                try {
                        welcomeSocket.close();
                        System.out.println("已停止服務");
                } catch (IOException e) {
                        System.out.println("無法停止服務");
                        System.exit(-1);
                }
        }
}

Worker

FTP傳輸工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
package ftp;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
//FTP傳輸工作
public class Worker extends Thread {   
         
        //TODO 使用者資料應採用認証服務機制
        private userStatus currentUserStatus = userStatus.NOTLOGGEDIN;
        private String validUser = "john";//單使用者帳號
        private String validPassword = "12345";//單使用者密碼
        // 主要路徑
        private String root;
        private String currDirectory;
        private String fileSeparator = "\\";
        // 傳輸元件
        private Socket controlSocket;
        private PrintWriter controlOutWriter;
        private BufferedReader controlIn;
        private ServerSocket dataSocket;
        private Socket dataConnection;
        private PrintWriter dataOutWriter;
        private int dataPort;
        private transferType transferMode = transferType.ASCII;
         
        private boolean quitCommandLoop = false;
         
        public Worker(Socket client, int dataPort) {
                super();
                this.controlSocket = client;
                this.dataPort = dataPort;
                this.root = System.getProperty("user.home");// 取得server上的JVM使用者目錄
                this.currDirectory = root + fileSeparator + "Desktop";// 嘗試存取桌面
        }
         
        public void run() {
                try {
                        controlIn = new BufferedReader(new InputStreamReader(controlSocket.getInputStream()));
                        controlOutWriter = new PrintWriter(controlSocket.getOutputStream(), true);
                        sendMsgToClient("220 歡迎訊息....");
                        while (!quitCommandLoop) {
                                executeCommand(controlIn.readLine());
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        try {
                                controlIn.close();
                                controlOutWriter.close();
                                controlSocket.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }
         
        //執行指令
        private void executeCommand(String c) {
                int index = c.indexOf(' ');
                String command = ((index == -1) ? c.toUpperCase() : (c.substring(0, index)).toUpperCase());
                String args = ((index == -1) ? null : c.substring(index + 1, c.length()));
                switch (command) {
                        case "USER":handleUser(args);break;
                        case "PASS":handlePass(args);break;
                        case "CWD":handleCwd(args);break;
                        case "LIST":handleNlst(args);break;
                        case "NLST":handleNlst(args);break;
                        case "PWD":handlePwd();break;
                        case "QUIT":handleQuit();break;
                        case "PASV":handlePasv();break;
                        case "EPSV":handleEpsv();break;
                        case "SYST":handleSyst();break;
                        case "FEAT":handleFeat();break;
                        case "PORT":handlePort(args);break;
                        case "EPRT":handlePort(parseExtendedArguments(args));break;
                        case "RETR":handleRetr(args);break;
                        case "MKD":handleMkd(args);break;
                        case "RMD":handleRmd(args);break;
                        case "TYPE":handleType(args);break;
                        case "STOR":handleStor(args);break;
                        default:sendMsgToClient("501 Unknown command");break;
                }
        }
         
        //一般訊息
        private void sendMsgToClient(String msg) {
                controlOutWriter.println(msg);
        }
         
        //狀態訊息
        private void sendDataMsgToClient(String msg) {
                if (dataConnection == null || dataConnection.isClosed()) {
                        sendMsgToClient("425 No data connection was established");
                } else {
                        dataOutWriter.print(msg + '\r' + '\n');
                }
        }
         
        private void openDataConnectionPassive(int port) {
                try {
                        dataSocket = new ServerSocket(port);
                        dataConnection = dataSocket.accept();
                        dataOutWriter = new PrintWriter(dataConnection.getOutputStream(), true);
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
         
        private void openDataConnectionActive(String ipAddress, int port) {
                try {
                        dataConnection = new Socket(ipAddress, port);
                        dataOutWriter = new PrintWriter(dataConnection.getOutputStream(), true);
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
         
        private void closeDataConnection() {
                try {
                        dataOutWriter.close();
                        dataConnection.close();
                        if (dataSocket != null) {
                                dataSocket.close();
                        }
                } catch (IOException e) {
                        e.printStackTrace();
                }
                dataOutWriter = null;
                dataConnection = null;
                dataSocket = null;
        }
         
        private void handleUser(String username) {
                if (username.toLowerCase().equals(validUser)) {
                        sendMsgToClient("331 User name okay, need password");
                        currentUserStatus = userStatus.ENTEREDUSERNAME;
                } else if (currentUserStatus == userStatus.LOGGEDIN) {
                        sendMsgToClient("530 User already logged in");
                } else {
                        sendMsgToClient("530 Not logged in");
                }
        }
         
        private void handlePass(String password) {
                if (currentUserStatus == userStatus.ENTEREDUSERNAME && password.equals(validPassword)) {
                        currentUserStatus = userStatus.LOGGEDIN;
                        sendMsgToClient("230-Welcome");
                        sendMsgToClient("230 User logged in successfully");
                }else if (currentUserStatus == userStatus.LOGGEDIN) {
                        sendMsgToClient("530 User already logged in");
                }else {
                        sendMsgToClient("530 Not logged in");
                }
        }
         
        private void handleCwd(String args) {
                String filename = currDirectory;
                if (args.equals("..")) {
                        int ind = filename.lastIndexOf(fileSeparator);
                        if (ind > 0) {
                                filename = filename.substring(0, ind);
                        }
                }else if ((args != null) && (!args.equals("."))) {
                        filename = filename + fileSeparator + args;
                }
                File f = new File(filename);
                if (f.exists() && f.isDirectory() && (filename.length() >= root.length())) {
                        currDirectory = filename;
                        sendMsgToClient("250 The current directory has been changed to " + currDirectory);
                } else {
                        sendMsgToClient("550 Requested action not taken. File unavailable.");
                }
        }
         
        private void handleNlst(String args) {
                if (dataConnection == null || dataConnection.isClosed()) {
                        sendMsgToClient("425 No data connection was established");
                } else {
                        String[] dirContent = nlstHelper(args);
                        if (dirContent == null) {
                                sendMsgToClient("550 File does not exist.");
                        } else {
                                sendMsgToClient("125 Opening ASCII mode data connection for file list.");
                                for (int i = 0; i < dirContent.length; i++) {
                                        sendDataMsgToClient(dirContent[i]);
                                }
                                sendMsgToClient("226 Transfer complete.");
                                closeDataConnection();
                        }
                }
        }
         
        private String[] nlstHelper(String args) {
                String filename = currDirectory;
                if (args != null) {
                        filename = filename + fileSeparator + args;
                }
                File f = new File(filename);
                if (f.exists() && f.isDirectory()) {
                        return f.list();
                } else if (f.exists() && f.isFile()) {
                        String[] allFiles = new String[1];
                        allFiles[0] = f.getName();
                        return allFiles;
                } else {
                        return null;
                }
        }
         
        private void handlePort(String args) {
                String[] stringSplit = args.split(",");
                String hostName = stringSplit[0] + "." + stringSplit[1] + "." + stringSplit[2] + "." + stringSplit[3];
                int p = Integer.parseInt(stringSplit[4]) * 256 + Integer.parseInt(stringSplit[5]);
                openDataConnectionActive(hostName, p);
                sendMsgToClient("200 Command OK");
        }
         
        private void handlePwd() {
                sendMsgToClient("257 \"" + currDirectory + "\"");
        }
         
        private void handlePasv() {            
                String myIp = "127.0.0.1";
                String myIpSplit[] = myIp.split("\\.");
                int p1 = dataPort / 256;
                int p2 = dataPort % 256;
                sendMsgToClient("227 Entering Passive Mode (" + myIpSplit[0] + "," + myIpSplit[1] + "," + myIpSplit[2] + ","+ myIpSplit[3] + "," + p1 + "," + p2 + ")");
                openDataConnectionPassive(dataPort);
        }
         
        private void handleEpsv() {
                sendMsgToClient("229 Entering Extended Passive Mode (|||" + dataPort + "|)");
                openDataConnectionPassive(dataPort);
        }
         
        private void handleQuit() {
                sendMsgToClient("221 Closing connection");
                quitCommandLoop = true;
        }
 
        private void handleSyst() {
                sendMsgToClient("215 COMP4621 FTP Server Homebrew");
        }
         
        private void handleFeat() {
                sendMsgToClient("211 END");
        }
         
        private void handleMkd(String args) {
                if (args != null && args.matches("^[a-zA-Z0-9]+$")) {
                        File dir = new File(currDirectory + fileSeparator + args);
 
                        if (!dir.mkdir()) {
                                sendMsgToClient("550 Failed to create new directory");
                        } else {
                                sendMsgToClient("250 Directory successfully created");
                        }
                } else {
                        sendMsgToClient("550 Invalid name");
                }
        }
         
        private void handleRmd(String dir) {
                String filename = currDirectory;
                if (dir != null && dir.matches("^[a-zA-Z0-9]+$")) {
                        filename = filename + fileSeparator + dir;
                        File d = new File(filename);
                        if (d.exists() && d.isDirectory()) {
                                d.delete();
                                sendMsgToClient("250 Directory was successfully removed");
                        } else {
                                sendMsgToClient("550 Requested action not taken. File unavailable.");
                        }
                } else {
                        sendMsgToClient("550 Invalid file name.");
                }
        }
         
        private void handleType(String mode) {
                if (mode.toUpperCase().equals("A")) {
                        transferMode = transferType.ASCII;
                        sendMsgToClient("200 OK");
                } else if (mode.toUpperCase().equals("I")) {
                        transferMode = transferType.BINARY;
                        sendMsgToClient("200 OK");
                } else
                        sendMsgToClient("504 Not OK");
        }
         
        private void handleRetr(String file) {
                File f = new File(currDirectory + fileSeparator + file);
                if (!f.exists()) {
                        sendMsgToClient("550 File does not exist");
                }else {
                        if (transferMode == transferType.BINARY) {
                                BufferedOutputStream fout = null;
                                BufferedInputStream fin = null;
                                sendMsgToClient("150 Opening binary mode data connection for requested file " + f.getName());
                                try {
                                        fout = new BufferedOutputStream(dataConnection.getOutputStream());
                                        fin = new BufferedInputStream(new FileInputStream(f));
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                                byte[] buf = new byte[1024];
                                int l = 0;
                                try {
                                        while ((l = fin.read(buf, 0, 1024)) != -1) {
                                                fout.write(buf, 0, l);
                                        }
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                                try {
                                        fin.close();
                                        fout.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                                sendMsgToClient("226 File transfer successful. Closing data connection.");
                        }else {
                                sendMsgToClient("150 Opening ASCII mode data connection for requested file " + f.getName());
                                BufferedReader rin = null;
                                PrintWriter rout = null;
                                try {
                                        rin = new BufferedReader(new FileReader(f));
                                        rout = new PrintWriter(dataConnection.getOutputStream(), true);
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
 
                                String s;
                                try {
                                        while ((s = rin.readLine()) != null) {
                                                rout.println(s);
                                        }
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                                try {
                                        rout.close();
                                        rin.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                                sendMsgToClient("226 File transfer successful. Closing data connection.");
                        }
                }
                closeDataConnection();
        }
         
        private void handleStor(String file) {
                if (file == null) {
                        sendMsgToClient("501 No filename given");
                } else {
                        File f = new File(currDirectory + fileSeparator + file);
 
                        if (f.exists()) {
                                sendMsgToClient("550 File already exists");
                        }else {
                                if (transferMode == transferType.BINARY) {
                                        BufferedOutputStream fout = null;
                                        BufferedInputStream fin = null;
                                        sendMsgToClient("150 Opening binary mode data connection for requested file " + f.getName());
                                        try {
                                                fout = new BufferedOutputStream(new FileOutputStream(f));
                                                fin = new BufferedInputStream(dataConnection.getInputStream());
                                        } catch (Exception e) {
                                                e.printStackTrace();
                                        }                                      
                                        byte[] buf = new byte[1024];
                                        int l = 0;
                                        try {
                                                while ((l = fin.read(buf, 0, 1024)) != -1) {
                                                        fout.write(buf, 0, l);
                                                }
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                        try {
                                                fin.close();
                                                fout.close();
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                        sendMsgToClient("226 File transfer successful. Closing data connection.");
                                }else {
                                        sendMsgToClient("150 Opening ASCII mode data connection for requested file " + f.getName());
 
                                        BufferedReader rin = null;
                                        PrintWriter rout = null;
                                        try {
                                                rin = new BufferedReader(new InputStreamReader(dataConnection.getInputStream()));
                                                rout = new PrintWriter(new FileOutputStream(f), true);
 
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
 
                                        String s;
 
                                        try {
                                                while ((s = rin.readLine()) != null) {
                                                        rout.println(s);
                                                }
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                        try {
                                                rout.close();
                                                rin.close();
                                        } catch (IOException e) {                                              
                                                e.printStackTrace();
                                        }
                                        sendMsgToClient("226 File transfer successful. Closing data connection.");
                                }
                        }
                        closeDataConnection();
                }
        }
         
        private String parseExtendedArguments(String extArg) {
                String[] splitArgs = extArg.split("\\|");
                String ipAddress = splitArgs[2].replace('.', ',');
                int port = Integer.parseInt(splitArgs[3]);
                int p1 = port / 256;
                int p2 = port % 256;
                return ipAddress + "," + p1 + "," + p2;
        }
         
        private enum transferType {
                ASCII, BINARY
        }
        private enum userStatus {
                NOTLOGGEDIN, ENTEREDUSERNAME, LOGGEDIN
        }
}

建立好的FTP Server可以用Windows內建的檔案總管檢視,但是下載客戶端軟體測試結果將較為準確。
大部份的FTP軟體對於UTF8的相容性極差,無論是客戶端或是伺服器端都有機會發生問題。本範例的客戶端以winscp為教具發生中文訊息的悲劇,因此所有訊息以原文輸出。

狀態碼

有興趣研究的人可以試著將狀態碼加入,並且嘗試更多的指令對應。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
private String getCodeMsg(String code) {               
                switch (code) {
                case "100": return "The requested action is being initiated, expect another reply before proceeding with a new command.";
                case "110": return "Restart marker replay . In this case, the text is exact and not left to the particular implementation; it must read: MARK yyyy = mmmm where yyyy is User-process data stream marker, and mmmm server's equivalent marker (note the spaces between markers and '=').";
                case "120": return "Service ready in nnn minutes.";
                case "125": return "Data connection already open; transfer starting.";
                case "150": return "File status okay; about to open data connection.";
                case "200": return "The requested action has been successfully completed.";
                case "202": return "Command not implemented, superfluous at this site.";
                case "211": return "System status, or system help reply.";
                case "212": return "Directory status.";
                case "213": return "File status.";
                case "214": return "Help message. Explains how to use the server or the meaning of a particular non-standard command. This reply is useful only to the human user.";
                case "215": return "NAME system type. Where NAME is an official system name from the registry kept by IANA.";
                case "220": return "Service ready for new user.";
                case "221": return "Service closing control connection.";
                case "225": return "Data connection open; no transfer in progress.";
                case "226": return "Closing data connection. Requested file action successful (for example, file transfer or file abort).";
                case "227": return "Entering Passive Mode (h1,h2,h3,h4,p1,p2).";
                case "228": return "Entering Long Passive Mode (long address, port).";
                case "229": return "Entering Extended Passive Mode (|||port|).";
                case "230": return "User logged in, proceed. Logged out if appropriate.";
                case "231": return "User logged out; service terminated.";
                case "232": return "Logout command noted, will complete when transfer done.";
                case "234": return "Specifies that the server accepts the authentication mechanism specified by the client, and the exchange of security data is complete. A higher level nonstandard code created by Microsoft.";
                case "250": return "Requested file action okay, completed.";
                case "257": return "'PATHNAME' created.";
                case "300": return "The command has been accepted, but the requested action is on hold, pending receipt of further information.";
                case "331": return "User name okay, need password.";
                case "332": return "Need account for login.";
                case "350": return "Requested file action pending further information";
                case "400": return "The command was not accepted and the requested action did not take place, but the error condition is temporary and the action may be requested again.";
                case "421": return "Service not available, closing control connection. This may be a reply to any command if the service knows it must shut down.";
                case "425": return "Can't open data connection.";
                case "426": return "Connection closed; transfer aborted.";
                case "430": return "Invalid username or password";
                case "434": return "Requested host unavailable.";
                case "450": return "Requested file action not taken.";
                case "451": return "Requested action aborted. Local error in processing.";
                case "452": return "Requested action not taken. Insufficient storage space in system.File unavailable (e.g., file busy).";
                case "500": return "Syntax error, command unrecognized and the requested action did not take place. This may include errors such as command line too long.";
                case "501": return "Syntax error in parameters or arguments.";
                case "502": return "Command not implemented.";
                case "503": return "Bad sequence of commands.";
                case "504": return "Command not implemented for that parameter.";
                case "530": return "Not logged in.";
                case "532": return "Need account for storing files.";
                case "534": return "Could Not Connect to Server - Policy Requires SSL";
                case "550": return "Requested action not taken. File unavailable (e.g., file not found, no access).";
                case "551": return "Requested action aborted. Page type unknown.";
                case "552": return "Requested file action aborted. Exceeded storage allocation (for current directory or dataset).";
                case "553": return "Requested action not taken. File name not allowed.";
                case "600": return "Replies regarding confidentiality and integrity";
                case "631": return "Integrity protected reply.";
                case "632": return "Confidentiality and integrity protected reply.";
                case "633": return "Confidentiality protected reply.";
                case "10000": return "Common Winsock Error Codes[2] (These are not FTP return codes)";
                case "10054": return "Connection reset by peer. The connection was forcibly closed by the remote host.";
                case "10060": return "Cannot connect to remote server.";
                case "10061": return "Cannot connect to remote server. The connection is actively refused by the server.";
                case "10066": return "Directory not empty.";
                case "10068": return "Too many users, server is full.";                
                default:
                        return "501 Unknown command";                  
                }
        }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
private String getCodeMsg(String code) { 
  switch (code) {
  case "110": return "重新啟動標記回覆。";
  case "120": return "服務就緒,在 nnn 分鐘。";
  case "125": return "資料連線已經開啟;傳輸開始。";
  case "150": return "檔案狀態無誤;將開啟資料連線。";
  case "200": return "指令已經沒有問題了。";
  case "202": return "在這個站台的指令不實作、 多餘。";
  case "211": return "系統狀態或系統說明回覆。";
  case "212": return "目錄狀態。";
  case "213": return "檔案狀態。";
  case "214": return "說明訊息。";
  case "215": return "名稱系統型別,其中名稱是一個正式的系統名稱從指派的數字的文件中的清單。";
  case "220": return "供新使用者的服務。";
  case "221": return "服務正在關閉控制連接。如果可以請登出。";
  case "225": return "資料連線已開啟;沒有正在傳輸中。";
  case "226": return "關閉資料連線。要求的檔案動作成功 (例如,檔案傳輸或檔案中止)。";
  case "227": return "進入被動模式 (h1、 h2、 h3、 h4、 p1,p2)。";
  case "229": return "延伸被動模式輸入。";
  case "230": return "使用者已登入,繼續執行。";
  case "232": return "已登入,使用者的權限的安全性資料交換。";
  case "234": return "的-安全性資料交換完成。";
  case "235": return "已順利完成安全性資料交換。";
  case "250": return "要求的檔案動作無誤,完成。";
  case "257": return "路徑名稱 」 建立。";
  case "331": return "的使用者名稱無誤,需要密碼。";
  case "332": return "需要登入帳戶。";
  case "334": return "要求安全性機制 [確定]。";
  case "335": return "安全性資料是可接受的。更多資料才能完成安全性資料交換。";
  case "336": return "使用者名稱無誤,需要密碼。";
  case "350": return "要求的檔案動作擱置中的其他相關資訊。";
  case "421": return "服務無法使用,正在關閉控制連接。如果服務知道其必須關閉,這可能是對任何命令的回覆。";
  case "425": return "無法開啟資料連接。";
  case "426": return "連接已關閉;傳輸中止。";
  case "431": return "需要某些無法使用的資源,處理安全性。";
  case "450": return "未採取要求的檔案動作。檔案無法使用 (例如,檔案忙碌)。";
  case "451": return "要求的動作已中止。正在處理本機錯誤。";
  case "452": return "要求未採取的動作。在系統中沒有足夠的儲存空間。";
  case "500": return "語法錯誤,無法辨認的命令。這可能包括命令列過長的錯誤。";
  case "501": return "參數或引數中的語法錯誤。";
  case "502": return "未執行命令。";
  case "503": return "錯誤的命令順序。";
  case "504": return "並未實作該參數的命令。";
  case "521": return "無法開啟 資料連線,使用這個連接埠正常設定。";
  case "522": return "伺服器不支援要求的網路通訊協定。";
  case "530": return "未登入。";
  case "532": return "需要帳戶以儲存檔案。";
  case "533": return "命令保護層級拒絕原則的原因。";
  case "534": return "原則原因拒絕要求。";
  case "535": return "(雜湊、 序列等等) 的失敗的安全性檢查。";
  case "536": return "要求的連接埠正常層級不支援的機制。";
  case "537": return "命令保護層級不支援的安全性機制。";
  case "550": return "要求未採取的動作。檔案無法使用 (例如,找不到檔案或沒有存取權)。";
  case "551": return "要求的動作已中止: 頁面類型不明。";
  case "552": return "要求的檔案動作已中止。超過儲存配置 (針對目前的目錄或資料集)。";
  case "553": return "要求未採取的動作。不允許的檔案名稱。";
  case "631": return "完整性保護回覆。";
  case "632": return "機密性和完整性保護回覆。";
  case "633": return "機密性保護回覆。";
  /*case "150": return "FTP 使用兩個連接埠: 21 傳送命令,而 20 用於傳送資料。狀態碼 150 表示伺服器將在連接埠 20開啟新的連線,以便傳送某些資料。";
  case "226": return "命令開啟資料連接在連接埠 20,要執行的動作,例如傳送檔案。已順利完成此動作,以及資料連線已關閉。";
  case "230": return "用戶端傳送正確的密碼之後,就會顯示此狀態碼。它會指出使用者已成功地登入。";
  case "331": return "用戶端傳送使用者名稱後,您會看到這個狀態碼。不論所提供的使用者名稱是否為系統上有效的帳戶,皆會出現相同的狀態碼。";
  case "426": return "命令開啟資料連線來執行動作,該動作已取消,但資料連線已關閉。";
  case "530": return "此狀態碼表示使用者無法登入,因為使用者名稱和密碼組合不正確。如果您利用使用者帳戶登入,則您可能輸入錯誤的使用者名稱或密碼,或您已選擇僅允許匿名存取。如果您使用「匿名」帳戶登入,您可能已設定 IIS 來拒絕匿名存取。";
  case "550": return "命令不會執行,因為指定的檔案無法使用。例如,當您嘗試取得的檔案不存在,或當您嘗試將檔案放置在沒有寫入權限的目錄中時,就會發生這個狀態碼。";*/
  
  default:
   return "501 Unknown command";  
  }
 }

中文的狀態輸出僅供參考...實作結果並不符合期待。

沒有留言:

張貼留言