Server
啟動FTP Server1 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" ; } } |
中文的狀態輸出僅供參考...實作結果並不符合期待。
沒有留言:
張貼留言