Страницы

Поиск по вопросам

суббота, 22 июня 2019 г.

Самописный СМТП-сервер

Я написал СМТП сервер, но работает он некорректно вот в каком моменте: если я 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; }
}
ВОПРОС:
Подскажите пожалуйста, как мне сделать так, чтобы мой сервис мог одинаково обслужить всех подключаемых клиентов, а не только первого?


Ответ

В подобных случаях обычно делают один поток слушатель, который прослушивает нужный порт. Когда подключается клиент создаётся новый поток для обслуживания непосредственно его и слушатель передаёт работу с клиентом этому потоку. При завершении клиентом работы с сервером этот поток уничтожается.
Приблизительно как-то так.

Комментариев нет:

Отправить комментарий