Я немного борюсь с программированием сокетов (что-то, с чем я совсем не знаком), и я не могу найти ничего, что поможет от Google или MSDN (ужасно). Извиняюсь за длину этого.
В основном у меня есть существующая служба, которая получает и отвечает на запросы по UDP. Я не могу изменить это вообще.
У меня также есть клиент в моем веб-приложении, который отправляет и прослушивает ответы на этот сервис. Существующий клиент, который мне дали, представляет собой синглтон, который создает сокет и массив слотов ответа, а затем создает фоновый поток с методом бесконечной цикличности, который выполняет «sock.Receive ()», вызывает и помещает полученные данные в массив слотов. Все эти вещи кажутся мне неправильными, и бесконечный поток прерывает мое модульное тестирование, поэтому я пытаюсь заменить этот сервис на другой, который вместо этого отправляет / получает асинхронно.
Пункт 1: Это правильный подход? Я хочу неблокируемый, масштабируемый, поточно-ориентированный сервис.
Моя первая попытка примерно такая, что сработало, но данные, которые я получил, всегда были короче, чем ожидалось (т. Е. В буфере не было запрошенного количества байтов), и казалось, что при обработке возникали исключения.
private Socket MyPreConfiguredSocket;
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
IAsyncResult h = this._sock.BeginReceiveFrom(response, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), this._sock);
if (!h.AsyncWaitHandle.WaitOne(TIMEOUT)) { throw new Exception("Timed out"); }
//process response data (always shortened)
}
private void ARecieve (IAsyncResult result)
{
int bytesreceived = (result as Socket).EndReceiveFrom(result, ref this._target);
}
Моя вторая попытка основывалась на большем количестве тралений в Google и на этом рекурсивном паттерне, который я часто видел, но эта версия всегда отключалась! Он никогда не доберется до ARecieve.
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
State s = new State(this.MyPreConfiguredSocket);
this.MyPreConfiguredSocket.BeginReceiveFrom(s.Buffer, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
if (!s.Flag.WaitOne(10000)) { throw new Exception("Timed out"); } //always thrown
//process response data
}
private void ARecieve (IAsyncResult result)
{
//never gets here!
State s = (result as State);
int bytesreceived = s.Sock.EndReceiveFrom(result, ref this._target);
if (bytesreceived > 0)
{
s.Received += bytesreceived;
this._sock.BeginReceiveFrom(s.Buffer, s.Received, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
}
else
{
s.Flag.Set();
}
}
private class State
{
public State(Socket sock)
{
this._sock = sock;
this._buffer = new byte[BUFFER_SIZE];
this._buffer.Initialize();
}
public Socket Sock;
public byte[] Buffer;
public ManualResetEvent Flag = new ManualResetEvent(false);
public int Received = 0;
}
Пункт 2: Ясно, что я что-то неправильно понимаю.
Пункт 3: Я не уверен, правильно ли я поступаю. Как данные, поступающие от удаленного сервиса, попадают в нужный поток прослушивания? Нужно ли создавать сокет для каждого запроса?
Из моей зоны комфорта здесь. Нужна помощь.