Я разрабатываю TCP-сервер в .NET C#. Он использует асинхронный ввод-вывод (ввод-вывод) для обработки большого количества клиентов одновременно. Сейчас у меня есть все TCP-соединения в списке, которые я просматриваю постоянно, ища изменения в конечной машине какого-либо конкретного соединения. Конечный автомат для данного соединения обновляется после завершения ввода/вывода определенных флагов.C# .NET Server опроса нескольких подключений - есть ли лучший способ?
Я уверен, что есть лучший способ сделать это - текущая реализация очень интенсивно обрабатывается процессором, так как я не блокирую ожидание обновления, а скорее опроса без дросселирования. Мне все равно, работает ли мой сервер в цикле, но я предполагаю, что это плохой дизайн. Я пытаюсь найти способ обработки конкретного соединения только тогда, когда сигналы завершения ввода-вывода есть что-то, что нужно обработать, и ждать (т. Е. Спать), когда нет. Может ли кто-нибудь предложить хороший способ сделать это?
Я думал, что некоторые функции синхронизации потоков могут работать там, где основной поток, который зацикливается, ждет завершения любого ввода-вывода, чтобы его освободить. Однако выполнение ввода-вывода иногда выполняется с использованием вызывающего потока (когда данные сразу доступны и т. Д.), Поэтому это может вызвать проблемы с этим решением.
Все, что вы можете предложить, было бы высоко оценено!
Здесь (упрощенный) цикл, который выполняется в главном потоке (rgClient список клиентов):
//Do communications on each client we currently have connected.
//This loops runs backwards so we can delete elements on the fly
//without have to iterate through more than once.
lock (rgClient)
{
for (i = rgClient.Count - 1; i >= 0; i--)
{
if (!rgClient[i].DoComm())
{
rgClient[i].DoClose();
rgClient.RemoveAt(i);
}
}
}
DoComm() выполняет обновление на конечный автомат для соединения, который включает в себя выполняя действия текущего состояния, а затем при необходимости перейдя в новое состояние. Вот это состояние класс для отправки простого пакета «Ack»:
class StateAck : State
{
public StateAck(TextBox txtOutputExt, Form fmOwner)
: base(txtOutputExt, fmOwner)
{
fWriting = false;
}
public override bool DoExecute(out Type tpNextState)
{
PktAck pkt;
if (!base.DoExecute(out tpNextState))
{
return false;
}
//Start a write if we haven't yet
if (!fWriting)
{
pkt = new PktAck();
fWriting = true;
return FPutPkt(pkt.rgbSerialize());
}
//Is the read finished/has an error occurred?
if (fDataErrorWrite)
{
return false;
}
//Process the data
if (fDataWritten)
{
tpNextState = typeof(StateIdle);
}
return true;
}
private bool fWriting;
}
Исполнения проходит через DoExecute() каждый раз, когда DoComm() вызывается из главного потока. В 99% случаев ничего не происходит. Когда запись (которая инициируется вызовом FPutPkt()) завершена, флаг будет сигнализировать об этом, а затем следующее состояние будет установлено на «холостой». Я хочу, чтобы основной поток проверял только те клиенты, которые завершили свою сетевую активность и что-то нужно для обновления, чтобы избежать постоянных и избыточных проходов через DoExecute().
Я бы предложил вам указать ваш код. Таким образом, у нас есть основа для обсуждения. –
И почему эта процедура обработки ввода-вывода не может обрабатываться? Разве это не все, что нужно для завершения ввода-вывода? –
вы можете проверить эту статью http://www.codeproject.com/KB/IP/dotnettcp.aspx – Iraklis