Проблемы с асинхронными UDP-сокетами - PullRequest
0 голосов
/ 15 мая 2009

Я немного борюсь с программированием сокетов (что-то, с чем я совсем не знаком), и я не могу найти ничего, что поможет от 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: Я не уверен, правильно ли я поступаю. Как данные, поступающие от удаленного сервиса, попадают в нужный поток прослушивания? Нужно ли создавать сокет для каждого запроса?

Из моей зоны комфорта здесь. Нужна помощь.

Ответы [ 4 ]

0 голосов
/ 08 апреля 2010

Одна ВОЗМОЖНАЯ проблема - если ваша операция отправки отправляется на сервер, и она отвечает до того, как Windows устанавливает асинхронный прослушиватель. Если вы не слушаете данные не будут приняты на вашей стороне (в отличие от TCP) Попробуйте вызвать beginread перед операцией отправки.

0 голосов
/ 15 мая 2009

Так выглядит ли ваша программа SUDO следующим образом?

Socket MySocket;
Socket ResponceSocket;

byte[] Request;
byte[] Responce;

public byte[] GetUDPResponce()
{
    this.MySocket.Send(Request).To(ResponceSocket);

    this.MySocket.Receive(Responce).From(ResponceSocket);

    return Responce;
}

Попробую помочь! Второй кодовый пост - это тот, с которым мы можем работать, и путь вперед.

Но вы правы! документация не самая лучшая.

0 голосов
/ 15 мая 2009

Вы точно знаете, что получили ответ на отправленное вами сообщение? Удалите асинхронное поведение из сокета и просто попытайтесь отправлять и получать синхронно (хотя это может заблокировать ваш поток на данный момент). Как только вы узнаете, что это поведение работает, отредактируйте свой вопрос и опубликуйте этот код, и я помогу вам с моделью потоков. Когда сетевая часть, то есть отправка / получение, работает, модель потоков довольно проста.

0 голосов
/ 15 мая 2009

Не решение для вас, просто предложение - придумайте простейший код, который удаляет все потоки / события / и т.д. Оттуда начните добавлять необходимые и только необходимые сложности. Мой опыт всегда заключался в том, что в процессе я найду, что делаю неправильно.

...