我如何让 TcpListener 接受多个连接并单独处理每个连接?
我有一个 SMTP 侦听器,运行良好,但只能接收一个连接。我的 C# 代码如下,我将其作为服务运行。我的目标是让它在服务器上运行并解析发送给它的多个 smtp 消息。
目前它解析第一条消息并停止工作。我怎样才能让它接受第二、第三、第四... SMTP消息并像第一个一样处理它?
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace SMTP_Listener
{
class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any , 8000);
TcpClient client;
NetworkStream ns;
listener.Start();
Console.WriteLine("Awaiting connection...");
client = listener.AcceptTcpClient();
Console.WriteLine("Connection accepted!");
ns = client.GetStream();
using (StreamWriter writer = new StreamWriter(ns))
{
writer.WriteLine("220 localhost SMTP server ready.");
writer.Flush();
using (StreamReader reader = new StreamReader(ns))
{
string response = reader.ReadLine();
if (!response.StartsWith("HELO") && !response.StartsWith("EHLO"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
string remote = response.Replace("HELO", string.Empty).Replace("EHLO", string.Empty).Trim();
writer.WriteLine("250 localhost Hello " + remote);
writer.Flush();
response = reader.ReadLine();
if (!response.StartsWith("MAIL FROM:"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
remote = response.Replace("RCPT TO:", string.Empty).Trim();
writer.WriteLine("250 " + remote + " I like that guy too!");
writer.Flush();
response = reader.ReadLine();
if (!response.StartsWith("RCPT TO:"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
remote = response.Replace("MAIL FROM:", string.Empty).Trim();
writer.WriteLine("250 " + remote + " I like that guy!");
writer.Flush();
response = reader.ReadLine();
if (response.Trim() != "DATA")
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
writer.WriteLine("354 Enter message. When finished, enter \".\" on a line by itself");
writer.Flush();
int counter = 0;
StringBuilder message = new StringBuilder();
while ((response = reader.ReadLine().Trim()) != ".")
{
message.AppendLine(response);
counter++;
if (counter == 1000000)
{
ns.Close();
return; // Seriously? 1 million lines in a message?
}
}
writer.WriteLine("250 OK");
writer.Flush();
ns.Close();
// Insert "message" into DB
Console.WriteLine("Received message:");
Console.WriteLine(message.ToString());
}
}
Console.ReadKey();
}
}
}
I have an SMTP listener that works well but is only able to receive one connection. My C# code is below and I am running it as a service. My goal is to have it runnign on a server and parsing multiple smtp messages sent to it.
currently it parses the first message and stops working. how can I get it to accept the 2nd, 3rd, 4th... SMTP message and process it like it does the first?
here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace SMTP_Listener
{
class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any , 8000);
TcpClient client;
NetworkStream ns;
listener.Start();
Console.WriteLine("Awaiting connection...");
client = listener.AcceptTcpClient();
Console.WriteLine("Connection accepted!");
ns = client.GetStream();
using (StreamWriter writer = new StreamWriter(ns))
{
writer.WriteLine("220 localhost SMTP server ready.");
writer.Flush();
using (StreamReader reader = new StreamReader(ns))
{
string response = reader.ReadLine();
if (!response.StartsWith("HELO") && !response.StartsWith("EHLO"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
string remote = response.Replace("HELO", string.Empty).Replace("EHLO", string.Empty).Trim();
writer.WriteLine("250 localhost Hello " + remote);
writer.Flush();
response = reader.ReadLine();
if (!response.StartsWith("MAIL FROM:"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
remote = response.Replace("RCPT TO:", string.Empty).Trim();
writer.WriteLine("250 " + remote + " I like that guy too!");
writer.Flush();
response = reader.ReadLine();
if (!response.StartsWith("RCPT TO:"))
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
remote = response.Replace("MAIL FROM:", string.Empty).Trim();
writer.WriteLine("250 " + remote + " I like that guy!");
writer.Flush();
response = reader.ReadLine();
if (response.Trim() != "DATA")
{
writer.WriteLine("500 UNKNOWN COMMAND");
writer.Flush();
ns.Close();
return;
}
writer.WriteLine("354 Enter message. When finished, enter \".\" on a line by itself");
writer.Flush();
int counter = 0;
StringBuilder message = new StringBuilder();
while ((response = reader.ReadLine().Trim()) != ".")
{
message.AppendLine(response);
counter++;
if (counter == 1000000)
{
ns.Close();
return; // Seriously? 1 million lines in a message?
}
}
writer.WriteLine("250 OK");
writer.Flush();
ns.Close();
// Insert "message" into DB
Console.WriteLine("Received message:");
Console.WriteLine(message.ToString());
}
}
Console.ReadKey();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以将大部分代码分解到一个单独的线程中:
You can factor out most of your code into a separate thread:
您几乎肯定希望将每个连接旋转到另一个线程中。因此,您在循环中进行了“accept”调用:
显然,您需要调整生成线程的方式(可能使用线程池,可能使用 TPL 等)以及如何优雅地停止侦听器。
You almost certainly want to spin each connection into another thread. So you have the "accept" call in a loop:
Obviously you'll want to adjust how you spawn threads (maybe use the thread pool, maybe TPL etc) and how you stop the listener gracefully.
我知道这是一个老问题,但我相信很多人会喜欢这个答案。
I know this is old question but I am sure many will like this answer.
迟到的回答是因为这个问题没有我正在寻找的答案。这就是我正在寻找的内容:
然后,当我在浏览器上向
http://localhost/foo
发出请求时,我得到以下信息:Late answer because this question did not had the answer that I was looking for. Here is what I was looking for:
Then when I make a request to
http://localhost/foo
on my browser I get this:根据您的代码,您将启动一个侦听器并接收和处理消息并关闭程序。
您需要维护一个侦听器,并将 TcpClient 对象传递给另一个函数来处理收到的消息。
监听器.Start();
As per your code, you are starting one listener and receiving and processing message and closing program.
You need to maintain a listener and TcpClient object can be passed to another function to process the message received.
listener.Start();