2011-10-15 35 views
2

我在從我連接到SMTP和POP服務器的套接字寫一個BufferedReader插座響應的文字讀取字符。但是,我怎麼知道我是否已經閱讀,直到回覆結束,以避免read()因讀取超出服務器響應而掛起?下面的代碼是如何,我從BufferedReader中閱讀:如何確定SMTP和POP響應的結束?

boolean endOfResponse = false; 
while(!endOfResponse) { 
    c = in.read(); 
    if ((c >= 32 && c < 127) || c == '\t' || c == '\r' || c == '\n') { 
     response.append((char)c); 
     //The following check has a problem: If the response has multiple lines, the other lines will not be read. 
     if(c == '\n') endOfResponse = true; 
    } 
} 

例如,POP,當我做了LIST,響應與.結束。但在SMTP中,當我執行EHLO時,它並沒有清楚地表明響應何時結束。

採用in.read() == -1,可悲的是,沒有工作,因爲它仍然會嘗試讀取超出響應數據,使插座掛起。

那麼,如何確定一個SMTP和POP的反應結束?更妙的是,甚至有可能事先知道我應該從緩衝區讀取多少字節,以便我甚至不必檢查響應的結束?

+0

您是否知道JavaMail的存在,實現所有這些協議並提供抽象他們上面一層? http://www.oracle.com/technetwork/java/javamail/index.html。即使你不想使用它,它也是開源的,所以你可能想看看它是如何工作的。 –

回答

9

的2個協議是不同的,但是兩者都發送其以換行符結束消息。使用SMTP,您一次只讀1行(以\ n結尾),您讀取的每行應該以3個數字開頭,然後是空格或' - '(如果是空格),那麼這是服務器響應的結束,如果它是一個「 - 」(像250-VRFY這是,如果你有EHLO開闢了你會得到什麼,促使服務器與擴展ESMTP命令列表響應),那麼你需要閱讀另一條線。

對於POP3,我相信這取決於你發出命令。像USER或PASS這樣的東西給你一個'+'或' - '的迴應(後面跟着一段代碼和一些文字)。像LIST這樣的命令給你一個'+'或' - ',如果'+',你會得到你的電子郵件列表,它將以一個'。'結尾。通過它自己。這些響應中的每一個(以及電子郵件的每個索引)都是一條線。

你應該看看RFC 821 for SMTPRFC 1939 for POP3拿到協議的詳細說明

+0

那麼在POP中,不同的命令有不同的結局?對於LIST和RETR,他們有一個'.'來結束。但對於某些命令,如USER和PASS,響應不會以'.'結尾。所以在我的代碼中,我必須區分不同的命令,並且不能使用通用方法來讀取所有命令的響應? – Carven

+0

是的,你需要知道你是否期待與POP3的多線迴應。例如,如果您發出LIST,則必須閱讀,直到您收到「。」。在一條線上。即使沒有什麼可以列出的。 –

+0

Jordan Stewart發佈了更新的RFC。 –

4

在SMTP從交易的服務器端的響應的結束可以通過查看響應代碼之後的字符來確定:它是一個「 - 」上除了最後一個響應的每一行中的狀態代碼後, line--

Client: EHLO my.mailserver.com 
Server: 123-This is a 
Server: 123 Multi-line response 

所以,SMTP(我還沒有處理POP之前,但它聽起來就像你已經工作,一出!),你需要檢查的這個「存在 - '字符在狀態代碼之後,以確定響應中是否有更多行。

當前SMTP RFC(5321)記載的:http://tools.ietf.org/html/rfc5321(例如第32頁)