2012-04-25 64 views
2

我正在尝试做一个简单的Gmail客户端。问题是我得到一个非常奇怪的回应;其实我根本没有得到SslStream.read的回应。首先,当我以客户端身份连接到Gmail服务器时,它的工作原理非常完美(Connect()方法),但是当我尝试从电子邮件中获取号码时,再次使用SslStream.readleerMensaje()方法,它变得很奇怪,只是停止运行,网页卡住加载。没有得到SslStream.read的响应

这里是我工作类:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Net; 
using System.Net.Sockets; 
using System.Net.Security; 
using System.Text; 
using System.Net.Mail; 

namespace GmailClient 
{ 
    public class GmailPop 
    { 
     private SslStream sslStream; 
     private String user; 
     private String pass; 

     public GmailPop(String user, String pass) 
     { 
      this.user = user; 
      this.pass = pass; 
     } 

     public bool Connect() 
     { 
      String response; 
      byte[] buffer = new byte[2048]; 
      int bytes = -1; 
      TcpClient server = new TcpClient("pop.gmail.com", 995); 
      sslStream = new SslStream(server.GetStream()); 
      sslStream.AuthenticateAsClient("pop.gmail.com"); 
      bytes = sslStream.Read(buffer, 0, buffer.Length); 
      response = Encoding.ASCII.GetString(buffer,0,bytes); 
      sslStream.Write(Encoding.ASCII.GetBytes("USER recent:" + user+"\r\n")); 
      bytes = sslStream.Read(buffer, 0, buffer.Length); 
      response = Encoding.ASCII.GetString(buffer,0,bytes); 
      if(response.StartsWith("+OK")){ 
       sslStream.Write(Encoding.ASCII.GetBytes("PASS "+pass+"\r\n")); 
       bytes = sslStream.Read(buffer,0,buffer.Length); 
       response = Encoding.ASCII.GetString(buffer, 0, bytes); 
       return response.StartsWith("+OK"); 
      } 
      return false; 
     } 
     public int numCorreos() 
     { 
      String res = escribirLeer("STAT"); 
      String[] resA = res.Split(' '); 
      int num = Int32.Parse(resA[1]); 
      return num; 
     } 
     public String leerMensaje() 
     { 
      int bytes = -1; 
      byte[] buffer = new byte[2048]; 
      String msg = ""; 
      do 
      { 
       bytes = sslStream.Read(buffer, 0, buffer.Length); 
       msg += Encoding.ASCII.GetString(buffer, 0, bytes); 
      } while (bytes != 0); 
      return msg; 
     } 
     public void escribirMsg(String msg) 
     { 
      byte[] buffer = Encoding.ASCII.GetBytes(msg); 
      sslStream.Write(buffer); 
      sslStream.Flush(); 
     } 
     public String escribirLeer(String msg) 
     { 
      escribirMsg(msg); 
      String respuesta = leerMensaje(); 
      return respuesta; 
     } 
    } 
} 

这里是ASPX网页调用该方法:

GmailPop client; 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      if (Session["user"] != null && Session["pass"] != null) 
      { 
       String user = Session["user"].ToString(); 
       String pass = Session["pass"].ToString(); 

       client = new GmailPop(user, pass); 

       if (client.Connect()) 
       {      
        Session["active"] = true; 
        Response.Write(numCorreos()); 
       } 
       else 
       { 
        Session.Remove("pass"); 
        Response.Redirect("login.aspx?error=login"); 
       } 
      } 
      else 
      { 
       Response.Redirect("login.aspx"); 
      } 
     } 
    } 

回答

1

第一个问题是,你发送“STAT “作为命令,但所有命令都必须以”\ r \ n“结尾,所以您需要发送”STAT \ r \ n“。

这似乎是你也推断从sslStream.Read(...)返回0代码的消息结束,但是这种方法将不会返回0,直到流被关闭。在没有更多数据等待读取的情况下,Read()将会阻塞,等待更多数据到达,这就解释了您所看到的挂起。

根据POP3 protocol specification,对于单行响应,您应该等待一个“\ r \ n”序列来指示响应的结束,以及对于那些导致多行响应的命令(例如,检索消息数据),响应由一个“。”结束。在一行上(即行以“。\ r \ n”开始)。处理包含此终止序列的消息还有其他规则,所以我建议您自己阅读协议规范。

+0

是的,我尝试了你所说的,实际上我在read方法的文档之前阅读,并且它返回读取的字节数,所以如果它在结束时应该返回0,问题是甚至在程序第一次达到该指令时调试程序,它只是在它运行该程序后立即停止调试。是一个很奇怪的行为。 – 2012-04-25 11:55:32

+0

第一次调用Read()时挂起的原因是因为命令必须以“\ r \ n”结尾。你只是发送“STAT”,但需要发送“STAT \ r \ n”。我将编辑我的答案以反映这一点。但是我的原始答案仍然存在 - 因为当前代码仍然期望Read()返回0(除非连接已关闭,否则它不会),所以即使您正确发送命令,它仍然会挂起,但是在第二次调用Read()。 – Iridium 2012-04-25 13:05:51

+0

谢谢你,我们有时候看不到的那些小聋人,因为你们正在上课后的午夜。再次感谢 – 2012-04-25 19:16:21