Вызов UdpClient.Send() внутри события System.Timers.Timer не работает

В моем приложении я получаю поток UDP и пересылаю его на две другие конечные точки UDP. Моя проблема в том, что мне нужно поместить задержку между двумя потоками, поэтому я решил использовать таймер. Это мой код (где я показываю только соответствующие методы):

public void Start()
{      
  Socket udpSocket = m_udpLocalClient.Client;

  udpSocket.ReceiveBufferSize = BUFFER_SIZE;

  // Enable broadcast
  udpSocket.SetSocketOption(SocketOptionLevel.Socket,
                            SocketOptionName.Broadcast,
                            1);
  // Enable reusing address
  udpSocket.SetSocketOption(SocketOptionLevel.Socket,
                            SocketOptionName.ReuseAddress,
                            true);

  // Bind the socket to the local endpoint and listen for incoming connections.
  udpSocket.Bind(new IPEndPoint(IPAddress.Any, m_ListenPort));

  m_udpLocalClient.JoinMulticastGroup(IPAddress.Parse(m_ListenIP));

  udpSocket.BeginReceiveFrom(m_data,
                             0,
                             m_data.Length,
                             SocketFlags.None,
                             ref m_ListenEndPoint,
                             new AsyncCallback(ReceiveData), 
                             m_udpLocalClient);
}

public void TimerCallback(object sender, ElapsedEventArgs e)
{
  byte[] Data = new byte[m_BytesReceived];

  m_Timer.Stop();

  m_Mutex.WaitOne();
  m_Buffer.Get(Data);
  m_Mutex.ReleaseMutex();

  //Send Packets lo LocalHost EndPoint
  m_udpLocalClient.Send(Data, Data.Length, m_LocalEndPoint);

}    

void ReceiveData(IAsyncResult iar)
{
  int recv = 0;

  try
  {
    UdpClient udpReceiver = (UdpClient)iar.AsyncState;

    recv = udpReceiver.Client.EndReceiveFrom(iar, ref m_ListenEndPoint);
    if (recv == 0)  return;

    //Forward packets on the FwEndpoint
    m_udpFwClient.Send(m_data, recv, m_FwEndPoint);

    //Send Packets lo LocalHost EndPoint
    //m_udpLocalClient.Send(m_data, recv, m_LocalEndPoint);

    m_Mutex.WaitOne();
    m_Buffer.Put(m_data);
    m_Mutex.ReleaseMutex();

    if (!m_Timer.Enabled) m_Timer.Start();

    udpReceiver.Client.BeginReceiveFrom(m_data, 
                                        0,
                                        m_data.Length, 
                                        SocketFlags.None,
                                        ref m_ListenEndPoint,
                                        new AsyncCallback(ReceiveData),
                                        udpReceiver);
  }
  catch (Exception e)
  {
     //...handle....
  }

}    

НОТА. Член m_Buffer является CircularBuffer от CodePlex.

Проблема здесь в том, что вызов

m_udpLocalClient.Send(Data, Data.Length, m_LocalEndPoint);

в TimerCallBack, кажется, не имеет никакого эффекта, в то время как я раскомментирую тот же самый в ReceiveData, он работает.

Я также пытаюсь использовать асинхронный метод BeginSend(), но безуспешно. Где я не прав?

С Уважением,
Даниэла.

1 ответ

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

Вам нужно будет использовать другой сокет /UdpClient для отправки данных в вашем обратном вызове таймера.

Другие вопросы по тегам