Я написал СМТП сервер, но работает он некорректно вот в каком моменте:
если я 1 раз подключусь к нему через телнет, он ответит нормально (рис 1-2.), но если я еще раз подключусь через другую консоль cmd, то я появится только черный экран и все(рис3):
(рис 1)
(рис 2)
(рис 3)
В последнем случае что-бы я ни вводил, на экране ничего не отобразится, и даже не залогируется моим СМТП
В первом же случае, мои команды отображаются в консоли, они логируюстя сервером и я вижу в этой консоли ответ (рис 4):
(рис 4)
Т.е., что я вижу, один клиент к нему подключается, работает нормально сервер, во всех остальных случаях он работает не корректно (верно?)
Вот как я реализовал СМТП-сервер (это win-сервис):
protected override void OnStart(string[] args)
{
SmtpHelper s = new SmtpHelper(this);
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(StartListen), (object)s );
}
void StartListen(object s)
{
try
{
var a = (SmtpHelper)s;
a.Listen(); //запуск
}
catch (Exception ex)
{
l.Write("Error (StartListen(object s)): " + ex.ToString());
throw;
}
}
public void Listen()
{
try
{
SMTP_Listener = new TcpListener(IPAddress.Any, port);
SMTP_Listener.Start();
while (true)
{
clientSocket = SMTP_Listener.AcceptSocket();
_sessionId = clientSocket.GetHashCode().ToString();
_email.sessionId = Convert.ToInt32(_sessionId);
StartProcessing(newController);
l.Write("we are there");
// System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ClientThread), SMTP_Listener.AcceptTcpClient());
}
}
catch (Exception ex)
{
l.Write("SMTP Listen Error: " + ex.ToString());
throw;
}
}
void StartProcessing(ClientSessionController newController)
{
try
{
m_ConnectedIp = ParseIP_from_EndPoint(clientSocket.RemoteEndPoint.ToString());
m_ConnectedHostName = GetHostName(m_ConnectedIp);
_email.ip = m_ConnectedIp;
_email.port = 25;
SendData("220 " + System.Net.Dns.GetHostName() + " Service ready
");
//if (!clientSocket.Connected)
// clientSocket.Connect(IPAddress.Any, port);
//РАБОТА С ВХОДНЫМИ ДАННЫМИ
while (true)
{
//если есть данные, то считаем их
if (clientSocket.Available > 0)
{
//получение команды от клиента
string lastCmd = ReadLine();
//парсим команду от клиента (HELO, RCPT, DATA etc.)
if (lastCmd.Trim() != String.Empty)
ProceedCommand(lastCmd, newController);
//break;
}
else
{
//dump: l.Write("[Socket isn't available now]");
}
}
}
catch (Exception ex)
{
throw;
}
}
ВОПРОС:
Подскажите пожалуйста, как мне сделать так, чтобы мой сервис мог одинаково обслужить всех подключаемых клиентов, а не только первого?
Ответ
В подобных случаях обычно делают один поток слушатель, который прослушивает нужный порт.
Когда подключается клиент создаётся новый поток для обслуживания непосредственно его и слушатель передаёт работу с клиентом этому потоку. При завершении клиентом работы с сервером этот поток уничтожается.
Приблизительно как-то так.
Комментариев нет:
Отправить комментарий