简体   繁体   中英

Loop for reading and decoding SSL message doesn't work

I have this loop to read and decode SSL message:

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());

When I debug it I see in "locals" tab that messageData's value is +OK Gpop ready for requests from xxx.xx.xx.xx p49mb48176339eey , but loop doesn't work and message isn't printed to console. Can somebody help me? If u want full code to test, it's here: github.com/WizzieP/MailerPrototype

The problem with your code is that a network TCP stream (and thus an SSL stream sitting on top of it) does not ever return 0 from Read() until the connection with the server is closed.

Because of this, you need to use other ways of figuring out if you've read all the data or not.

In your case, since you are trying to read a POP3 server greeting, what you want to do is to keep looping until you've read a "\\r\\n" sequence (you could also simply check for '\\n' as well).

When you go to implement the CAPA, UIDL, STAT, TOP, and RETR commands, you'll want to continue looping until you receive "\\r\\n.\\r\\n" .

If you would like to see some advanced techniques on how to do this, feel free to browse my code at https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Stream.cs#L394 (the line # may change, but look for the Read (byte[] buffer, int offset, int count, CancellationToken cancellationToken) method).

What this method does is prevent the consumer of this stream from reading beyond the end of a response to a command such as RETR and TOP. While doing that, it also un-byte-stuffs the data being read from the network (the POP3 server will 'byte-stuff' by prepending a '.' to every line that begins with a '.' in the RETR and TOP responses) so that the consumer can simply read the stream as if it were reading the raw message from disk and not have to worry about handling any of that.

In order to do that, you'll notice that Pop3Stream buffers data. That's what the ReadAhead() method is responsible for.

This is all designed so that I can parse the message more-or-less directly from the socket rather than reading all of the data into 1 big StringBuffer before parsing it: https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Client.cs#L1275

Between this and the fact that my MIME parser parses the message incrementally (rather than reading the entire message into 1 big StringBuffer) is what makes my code so incredibly fast compared to all of the other .NET POP3 libraries.

Good luck!

I removed the loop and some code and it worked. I took code in the answer from stackoverflow, so I was suprised it hadn't worked. Here is my new code:

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM