简体   繁体   English

自动刷新TCP流不起作用

[英]Auto flush of tcp stream doesn't work

As you may see I work a little SMTP server written in C#. 您可能会看到,我使用C#编写了一些SMTP服务器。 I included whole code (one class is not included), but I hope you get good view of detail. 我包括了完整的代码(不包括一个类),但我希望您能对细节有所了解。 I am struggeling at the DATA post from the client, the problem is in my point of view the not working "Auto Flush". 我在客户端的DATA帖子中苦苦挣扎,从我的角度来看,问题是无法正常工作的“自动冲洗”。 The client sends to my server "DATA" to tell me to get ready to receive data for my email. 客户端将“ DATA”发送到我的服务器,告诉我准备好接收我的电子邮件的数据。 I need to answer "354 start mail input", which I do, my problem is: After sending "354 start mail input" I need to receive the message from client in this funtion. 我需要回答“ 354开始邮件输入”,我的问题是:发送“ 354开始邮件输入”后,在此功能中,我需要从客户端接收消息。

 using System;
 using System.Text;
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;

namespace FakeSMTP
{
public class SMTPServer //: IDisposable
{
    TcpClient client;
    NetworkStream stream;
    System.IO.StreamReader reader;
    System.IO.StreamWriter writer;
    //public void Dispose()
    //{
    //    writer.Dispose();
    //    reader.Dispose();
    //    stream.Dispose();
    //}


    public SMTPServer(TcpClient client)
    {
        this.client = client;
        stream = client.GetStream();
        reader = new System.IO.StreamReader(stream);
        writer = new System.IO.StreamWriter(stream);
        writer.NewLine = "\r\n";
        writer.AutoFlush = true;
    }

    static void Main(string[] args)
    {
        TcpListener listener = new TcpListener(IPAddress.Loopback, 25);
        listener.Start();
        //using (SMTPServer handler = new SMTPServer(listener.AcceptTcpClient()))
        while (true)
        {
            SMTPServer handler = new SMTPServer(listener.AcceptTcpClient());
            Thread thread = new System.Threading.Thread(new ThreadStart(handler.Run));
            thread.Start();
        }
    }

    public void Run()
    {

        string sadress;
        string radress;
        string rserver;
        bool auth = false;
        writer.WriteLine("220 smtp.localsmtp.de ESMTP server ready");
        for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
        {
            Console.Error.WriteLine("Read line {0}", line);

            if (line.StartsWith("EHLO"))
                {
                writer.WriteLine("250-smtp.localsmtp.de");
                //Auth ankuendigen
                writer.WriteLine("250 AUTH PLAIN");
                }

            if (line.StartsWith("QUIT"))
                {
                writer.WriteLine("221 Bye Sweetie see ya");
                client.Close();
                }

            #region auth

            if (line.StartsWith("AUTH PLAIN"))
            {
                Console.WriteLine("client sendet Auth: " + line);
                string [] pw = line.Split(new string[] { "PLAIN " }, StringSplitOptions.None);
                byte[] bytes = Convert.FromBase64String(pw[1]);
                string result = Encoding.BigEndianUnicode.GetString(bytes);

                if (result == "12")
                    {
                        writer.WriteLine("235 2.7.0 Authentication successful");
                        auth = true;
                    }
                else
                    {
                        Console.WriteLine("Falsche AUTH Daten");
                        writer.WriteLine("535 – Incorrect authentication data");

                    }
            }
                #endregion

            #region sender
            if (line.StartsWith("MAIL FROM") && auth == true)
                 {
                 string[] sadressa = line.Split(new string[] { "FROM:" }, StringSplitOptions.None);
                 sadress = sadressa[1];
                 //Absender
                 sadress = sadress.Replace("<","").Replace(">","");
                 //Debug
                 Console.WriteLine("Absender: " + sadress);
                 writer.WriteLine("250 OK");
                 }

            #endregion

            #region receiver
            if (line.StartsWith("RCPT TO:") && auth == true)
                {
                    string[] radressa = line.Split(new string[] { "RCPT TO:" }, StringSplitOptions.None);
                    radress = radressa[1];
                    //Empfänger
                    radress = radress.Replace("<", "").Replace(">", "");
                    if (samplesmtp.getMX.GetMXRecord(radress) != "invalid")
                    {
                        rserver = samplesmtp.getMX.GetMXRecord(radress);
                        Console.WriteLine("MX Record: " + rserver);
                    }
                    else
                        Console.WriteLine("ALARM");


                    //Debug
                    Console.WriteLine("Empfänger: " + radress);
                    writer.WriteLine("250 OK");
                }
            #endregion

            #region data

            if (line.StartsWith("DATA") && auth == true)
            {
               writer.WriteLine("354 start mail input");

               var emailLine = reader.ReadLine();
               while (!emailLine.Equals("."))
               {
                   // add emailLine to the email body
                   string[] emailbody = new string[] {emailLine};
                   Console.WriteLine("Emailbody: " + emailbody[0]); 
               }
               reader.Close();
               writer.Close();
               stream.Dispose();
               writer.WriteLine("250 OK");
            }

            #endregion

        }
        }
    }
}

Trying to call .Flush() manually in code doesn't change the problem at all. 尝试在代码中手动调用.Flush()根本不会改变问题。 No effect. 没有效果。

In response to your comment to mine: 回应您对我的评论:

public class SMTPServer : IDisposable
{
    // all the other stuff

    public void Dispose()
    {
        writer.Dispose();
        reader.Dispose();
        stream.Dispose();
    }
}

calling code: 调用代码:

static void Main(string[] args)
{
    TcpListener listener = new TcpListener(IPAddress.Loopback, 25);
    listener.Start();
    using (SMTPServer handler = new SMTPServer(listener.AcceptTcpClient()))
    {
        while (true)
        {
            Thread thread = new System.Threading.Thread(new ThreadStart(handler.Run));
            thread.Start();
        }
    }
}

In answer to your actual question you want to read all the lines until you receive a . 为了回答您的实际问题,您需要阅读所有内容,直到收到。 on a line on it's own (see https://www.ietf.org/rfc/rfc2821.txt ), something like this: - 单独显示一行(请参阅https://www.ietf.org/rfc/rfc2821.txt ),如下所示:-

var emailLine = reader.ReadLine();
while (!emailLine.Equals("."))
{
   // add emailLine to the email body
   emailLine = reader.readLine();
}
writer.WriteLine("250 OK");
reader.Close();
writer.Close();
stream.Dispose();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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