用于读取和解码SSL消息的循环不起作用

时间:2014-07-11 12:37:23

标签: c# sockets ssl tcp pop3

我有这个循环来读取和解码SSL消息:

byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
// Works well to this moment
do
{
    bytes = sslStream.Read(buffer, 0, buffer.Length);
    Decoder decoder = Encoding.UTF8.GetDecoder();
    char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
    decoder.GetChars(buffer, 0, bytes, chars, 0);
    messageData.Append(chars);

    if (messageData.ToString().IndexOf("<EOF>") != -1)
        break;
} while (bytes != 0);
Console.Write(messageData.ToString());

当我调试它时,我会看到&#34;本地人&#34;标签messageData的值为+OK Gpop ready for requests from xxx.xx.xx.xx p49mb48176339eey,但循环不起作用且消息未打印到控制台。有人能帮助我吗?如果您想要完整的代码进行测试,请访问:github.com/WizzieP/MailerPrototype

2 个答案:

答案 0 :(得分:1)

您的代码存在的问题是,在与服务器的连接关闭之前,网络TCP流(以及位于其上的SSL流)不会从Read()返回0。

因此,您需要使用其他方法来确定您是否已阅读所有数据。

在您的情况下,由于您尝试阅读POP3服务器问候语,您要做的是保持循环,直到您阅读"\r\n"序列(您也可以只检查'\ n'同样)。

当您开始实施CAPA,UIDL,STAT,TOP和RETR命令时,您需要继续循环,直到收到"\r\n.\r\n"

如果您希望了解有关如何执行此操作的一些高级技巧,请随时在https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Stream.cs#L394浏览我的代码(#行可能会更改,但请查找Read (byte[] buffer, int offset, int count, CancellationToken cancellationToken)方法)。< / p>

此方法的作用是防止此流的使用者在对RETR和TOP等命令的响应结束之后进行读取。在这样做的同时,它也会对从网络读取的数据进行非字节填充(POP3服务器将通过将'.'添加到以'.'开头的每一行来“填充字节”。 RETR和TOP响应)这样消费者就可以简单地读取流,就像从磁盘读取原始消息一样,而不必担心处理任何这些消息。

为了做到这一点,你会注意到Pop3Stream缓冲数据。这就是ReadAhead()方法的责任。

这一切都是为了让我能够直接从套接字解析消息,而不是在解析它之前将所有数据读入1个大的StringBuffer:https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Client.cs#L1275

在此之间以及我的MIME解析器以递增方式解析消息(而不是将整个消息读入1个大型StringBuffer)这一事实使我的代码与所有其他.NET POP3库相比非常快。

祝你好运!

答案 1 :(得分:-1)

我删除了循环和一些代码并且它有效。我从stackoverflow中得到了代码,所以我很惊讶它没有用。这是我的新代码:

byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = 0;
bytes = sslStream.Read(buffer, 0, buffer.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);

Console.Write(messageData.ToString());