Я ищу лучшие практики, отвечающие следующим требованиям:
- Фреймворк, который обрабатывает несколько клиентских сокетов асинхронно.
- Каждый протокол входящих сообщений требует, чтобы каждое сообщение было форматной строкой и помечено как завершенное символом перевода строки '\ n'.
- Я полностью контролирую клиентскую сторону, но не сервер. Сервер принимает и отправляет сообщения на основе строк с символом перевода строки, чтобы отметить завершение сообщения.
- Я хочу иметь возможность отправлять сообщения через каждый подключенный сокет в любой момент времени (каждый сокет может получать и отправлять сообщения).
- Входящие сообщения следует пересылать через обратный вызов.
- Я хочу иметь возможность выбирать в своей реализации, будут ли все входящие полные сообщения от всех подключенных сокетов перенаправляться на один единственный обратный вызов или каждый клиент сокета реализует свой собственный обратный вызов.
- Я подключаю максимум 4 клиента / сокета. Поэтому я ищу предложения, которые используют такое ограниченное количество сокетов, но способны управлять всеми ими одновременно.
Интересно, является ли структура, в которой я использую BeginReceive
и EndReceive
с реализованным обратным вызовом IAsyncResult, современным, учитывая, что я нацелен на .Net 4.5. Есть ли лучшее решение, например использование NetworkStream или других вариантов API? Что действительно беспокоит меня в реализации BeginReceive / EndReceive, так это то, что после EndReceive я должен снова вызвать BeginReceive и снова зарегистрировать обратный вызов. Для меня это звучит как огромные накладные расходы. Почему нельзя добавлять новые данные асинхронно в любое время, и в то же время другой контекст создает полные сообщения, которые затем маршрутизируются через вызванное событие?
Аргумент использования IAsyncResult часто приводится в том, что обработка потока выполняется, но что говорит против следующего: использование NetworkStream и простое чтение и запись в поток. Как уже упоминалось, обмениваются только строковыми сообщениями, и каждое сообщение по протоколу помечается как завершенное символом перевода строки. Отдельная задача / поток опрашивает потоковый ридер (на основе сетевого потока) через ReadLine()
. Наверное, не может быть проще, не так ли?
В основном я спрашиваю, как сделать следующий код действительно асинхронным?
public class SocketClient
{
private TcpClient client;
private StreamReader reader;
private StreamWriter writer;
public event Action<string> MessageCallback;
public SocketClient(string hostname, int port)
{
client = new TcpClient(hostname, port);
try
{
Stream stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.AutoFlush = true;
//Start Listener on port
StartListener();
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
}
public void StartListener()
{
Task task = Task.Factory.StartNew(() =>
{
while (true)
{
if (MessageCallback != null)
{
MessageCallback(reader.ReadLine());
}
//Thread.Sleep(200);
}
});
}
}