2012-10-26 46 views
7

मेरी समस्या यह है कि मैं एक एफ़टीपी क्लाइंट बना रहा हूं, और अब तक यह एक मामूली विस्तार के अलावा बिना काम कर रहा है, जो मुझे परेशान करता रहता है। मुझे यह जानने की ज़रूरत है कि एफ़टीपी स्वागत संदेश कितने लाइनों पर फैलता है ... और यह स्वीकार्य नहीं हो सकता है!एफ़टीपी स्वागत संदेश के अंत को कैसे जानें

private Socket connection; 
    private PrintWriter outStream; 
    private Scanner inStream; 

public void InitiateConnection() throws IOException 
{ 
    log.Info(this, "Initiating connection to host: " + host + ":" + port); 
    connection = new Socket(host, port); 
    log.Info(this, "Connection initiated."); 
    outStream = new PrintWriter(connection.getOutputStream(), true); 
    inStream = new Scanner(connection.getInputStream()); 
    Listen(); 
    Listen();  
    Listen(); 
} 

public String Listen() throws IOException 
{ 
    if(connection == null) 
     throw new IOException("Connection not initiated yet"); 
    String response = inStream.nextLine(); 
    log.Info(this, "Response: " + response); 
    return response; 
} 

यह एक आसान सेटअप है, मैंने अन्य सभी कोड छोड़ दिए हैं, क्योंकि इसमें मेरी समस्या से कोई लेना देना नहीं है।

मैंने इसे प्राप्त करने का प्रयास करने के लिए कई चीजों की कोशिश की है। विफल समाधान 1:

String response = ""; 
while(response != null) 
    Listen(); 

विफल समाधान 2:

while(connection.getInputStream().available > 0) 
    Listen(); 

और अनगिनत दूसरों ... लेकिन या तो यह काम नहीं करता, या तरीकों ब्लॉक और नए इनपुट के लिए प्रतीक्षा करें। मैंने टाइमआउट के साथ भी कोशिश की है, लेकिन यह बेकार ढंग से काम नहीं करता है, यह इस समस्या का उचित समाधान नहीं है ...

मुझे बिना किसी जानकारी के एफ़टीपी सर्वर से पूरा स्वागत संदेश प्राप्त करने में सक्षम होना चाहिए

Response: 220-FileZilla Server version 0.9.39 beta 
Response: 220-written by Tim Kosse ([email protected]) 
Response: 220 Please visit http://sourceforge.net/projects/filezilla/ 

और यह:

Response: 220-FileZilla Server version 0.9.40 beta 
Response: 220 Welcome to Andrés FTP Server 

उत्तर

7

, आप देखते हैं कि सभी लेकिन पिछले लाइनों स्थिति कोड के पीछे एक - है। आखिरी पंक्ति में है, हालांकि, अंतिम पंक्ति को इंगित करता है।

आपको लगता है कि पढ़ सकते हैं RFC 959 में, खंड 4.2:

इस प्रकार बहु ​​लाइन के लिए प्रारूप जवाब दिया कि पहली पंक्ति सटीक आवश्यक जबाब कोड के साथ शुरू हो जाएगा, एक हाइफन से तुरंत पीछा किया, "-" (जिसे मिनस भी कहा जाता है), टेक्स्ट के बाद। आखिरी पंक्ति उसी कोड से शुरू होगी, तुरंत अंतरिक्ष द्वारा, वैकल्पिक रूप से कुछ पाठ, और टेलनेट अंत-रेखा कोड के बाद शुरू होगी।

दूसरी से दूसरी-आखिरी पंक्ति के बारे में कुछ भी नहीं कहा गया है, लेकिन यह तर्कसंगत है कि उनके पास पहले प्रारूप के समान प्रारूप है।


अद्यतन: FTP प्रोटोकॉल बुरी तरह से प्रलेखित किया जा रहा है, लेकिन मैं मेरे ऊपर के रूप में एक और संदर्भ में एक ही बताते हुए पाया:

TCP/IP Guide कहा गया है कि

यह एक उत्तर के लिए संभव है पाठ की एक से अधिक पंक्तियों को शामिल करने के लिए। इस मामले में, प्रत्येक पंक्ति उत्तर कोड के साथ शुरू होती है, और सभी पंक्तियां लेकिन आखिरी बार उत्तर कोड और उत्तर टेक्स्ट के बीच एक हाइफ़न होता है, यह इंगित करने के लिए कि उत्तर जारी है। अंतिम पंक्ति में उत्तर कोड और उत्तर टेक्स्ट के बीच एक स्थान होता है, बस एक सिंगल-लाइन उत्तर की तरह। यह सुविधा अक्सर 230 उत्तर कोड के माध्यम से उपयोगकर्ता लॉग इन करने के बाद अतिरिक्त प्रतिक्रिया जानकारी प्रदान करने के लिए उपयोग की जाती है।

+0

यह * multiline * उत्तर प्रारूप है। उसी खंड से: "एक एफ़टीपी उत्तर में तीन अंकों की संख्या होती है (तीन अल्फान्यूमेरिक वर्णों के रूप में प्रेषित) कुछ पाठ के बाद।" यह spec से स्पष्ट नहीं है लेकिन यदि आप FileZilla स्टार्टअप करते हैं तो आप देखेंगे कि कनेक्ट प्रक्रिया में केवल एमएल प्रतिक्रिया FEAT कमांड पर 211 प्रतिक्रिया है। – linski

+0

तदनुसार अद्यतन करेगा :) – linski

0

आप इस तरह की कोशिश की है लाइनों की राशि ... इसलिए मैं दोनों इस मिल सकता है?

StringBuilder response = new StringBuilder(); 
    BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); 
    do {    
     response.append(br.readLine());          
    } 
    while (br.ready()); 

BufferedReader के ready() विधि जबकि:

बताता है कि क्या यह धारा पढ़ा जा करने के लिए तैयार है। यदि बफर खाली नहीं है, या अंतर्निहित चरित्र स्ट्रीम तैयार है तो एक बफरर्ड वर्ण स्ट्रीम तैयार है।
रिटर्न:
सही अगर अगला पढ़ा जाता है() इनपुट के लिए अवरुद्ध नहीं होने की गारंटी है, तो अन्यथा झूठी। ध्यान दें कि झूठी वापसी से यह गारंटी नहीं मिलती है कि अगला पढ़ा जाएगा।

यह वास्तव में Reader का method है।

अद्यतन:

रूप glglgl ने बताया वहाँ एफ़टीपी में प्रतिक्रियाओं के दो प्रकार हैं:

  • "एक पंक्ति" प्रतिक्रिया (मेरे शब्द)
  • बहु प्रतिक्रिया (कल्पना अवधि)

जैसा कि मैंने टिप्पणी में कहा था, FIlleZilla को आग लगाना, लॉग को कनेक्ट करना और निरीक्षण करना (विशेष रूप से spec defintion के साथ आउटपुट में कमांड की तुलना करना) और आप देखेंगे कि "सिंगल लाइन" उद्धृत किया गया है।

कुछ एफ़टीपी सर्वर कार्यान्वयन पर उपरोक्त कोड काम कर सकता है, लेकिन यह सभी कार्यान्वयन पर काम नहीं करेगा, क्योंकि यह प्रोटोकॉल के क्लाइंट भाग को सही ढंग से लागू नहीं करता है।इस अद्यतन संस्करण है: यदि आप संदेशों पर एक करीबी नजर है, तो

String response; 
List<String> responseList = new ArrayList<String>(); 
boolean isMultilineStart = false, isMultilineEnd = false; 
String mlCode = null; 
do {    
    responseList.add(br.readLine());       
    if (!isMultilineStart) { 
     isMultilineStart = responseList.get(responseList.size()-1).matches("\\d\\d\\d-.*");     
     mlCode = responseList.get(responseList.size()-1).substring(0,3); 
    } 
    else { 
     isMultilineEnd = responseList.get(responseList.size()-1).startsWith(mlCode+" "); 
    } 
} 
while (br.ready() || (isMultilineStart && !isMultilineEnd)); 
response = Arrays.deepToString(responseList.toArray()); 
+0

नहीं, मेरे पास नहीं है, लेकिन मैं निश्चित रूप से इसे आजमाने की कोशिश कर रहा हूं। –

+1

लेकिन आप नहीं जानते कि सर्वर वास्तव में समाप्त हो गया है, या यदि कोई पैकेट रास्ते में है, लेकिन अभी तक नहीं पहुंचा है। प्रोटोकॉल द्वारा प्रदान की जाने वाली सुविधाओं पर बेहतर भरोसा करें। – glglgl

+0

@glglgl "मेरी समस्या यह है कि मैं एक एफ़टीपी क्लाइंट बना रहा हूं ..." ऐसा लगता है कि वह प्रोटोकॉल के क्लाइंट साइड को कार्यान्वित कर रहा है। – linski