C#: Socket - многоадресная передача, данные не получены, обратный вызов BeginReceive/BeginReceiveFrom не вызывается
Я на самом деле в растерянности, у меня есть эта проблема в течение некоторого времени. Я искал Stackru и не мог найти решение.
Проблема заключается в следующем: я не получаю никаких данных, и Callback из BeginReceive или BeginReceiveFrom из Socket (multicast) никогда не вызывается, и данные никогда не обрабатываются, и я не могу найти причину. Я не вижу лес за деревьями:(
Если я отлаживаю приложение шаг за шагом, я иногда получаю данные, а иногда нет. Если я отлаживаю без точек останова и без "пошагового", это никогда не сработает.
Когда я снимаю адрес многоадресной рассылки с помощью wireshark, я вижу прибывающие пакеты, и я знаю, что пакеты отправляются сервером каждые 500 мс.
Вот код для программы UnitTest и инициализация сокета, подключение и получение.
Может быть, кто-то может помочь мне найти ошибку или указать мне правильное направление...
Вот как я инициализирую сокет:
public void Initialize()
{
IPAddress multicastIP = IPAddress.Parse(mcastConfig.RemoteIPAddress);
IPAddress localIP = IPAddress.Parse(mcastConfig.LocalIPAddress);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_socket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.NoDelay, 1);
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPEndPoint localEP = new IPEndPoint(localIP, mcastConfig.RemotePort);
_socket.Bind(localEP);
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 5);
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)localIP.Address);
multicastEndPoint = new IPEndPoint(multicastIP, mcastConfig.RemotePort);
MulticastOption mcastOption = new MulticastOption(multicastIP, localIP);
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);
Connect();
}
AsyncConnect работает нормально, это выглядит так:
public void Connect()
{
if (!Connected)
{
_socket.BeginConnect(multicastEndPoint, new AsyncCallback(ConnectCallback), _socket);
connectDone.WaitOne();
Connected = true;
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
connectDone.Set();
}
catch (Exception e)
{
_log.Error("### Error with the Connection: {0}", e.ToString());
}
}
Проблема начинается с BeginReceive, он вызывается один раз, но потом ничего не происходит, а сам обратный вызов вызывается только тогда, когда сокет закрыт (как и должно быть, уже прочитал это здесь):
public void Receive()
{
byte[] data = new byte[_buffer.Length];
if (!Connected)
{
Connect();
}
try
{
mcastEP = multicastEndPoint;
IPAddress localIP = IPAddress.Parse(mcastConfig.LocalIPAddress);
EndPoint localEP = new IPEndPoint(localIP, mcastConfig.RemotePort);
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
//_socket.BeginReceiveFrom(_buffer, 0, _buffer.Length, SocketFlags.None, ref localEP, new AsyncCallback(ReceiveCallback), _socket);
Array.Copy(_buffer, data, _buffer.Length);
pDUHelper.ProcessData(data); //This processes the data and sends an event if the data was correct received
}
catch (SocketException se)
{
_log.Error("### SocketException ErrorCode: {0}, see: https://support.microsoft.com/en-us/help/819124/windows-sockets-error-codes-values-and-meanings", se.ErrorCode.ToString());
}
catch(Exception e)
{
_log.Error(e);
}
}
private void ReceiveCallback(IAsyncResult ar)
{
Socket socket = ar.AsyncState as Socket;
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);
EndPoint ep = ipep;
try
{
int reicevedBytes = _socket.EndReceive(ar);
//int reicevedBytes = _socket.EndReceiveFrom(ar, ref ep);
ipep = ep as IPEndPoint;
if(reicevedBytes > 0)
{
byte[] data = new byte[reicevedBytes];
Array.Copy(_buffer, data, reicevedBytes);
pDUHelper.ProcessData(data); //This processes the data and sends an event if the data was correct received
receiveDone.Set();
}
}
catch (ObjectDisposedException ode)
{
_log.Error(ode);
}
catch (SocketException se)
{
_log.Error(se);
}
catch(Exception e)
{
_log.Error(e);
}
finally
{
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
//_socket.BeginReceiveFrom(_buffer, 0, _buffer.Length, SocketFlags.None, ref ep, new AsyncCallback(ReceiveCallback), _socket);
}
}
Моя программа модульных испытаний
class Program
{
static ConcurrentQueue<CallListLine> _workerQueue = new ConcurrentQueue();
static void Main(string[] args)
{
Console.WriteLine("Create Configuration");
ConfigurationHelper.Configuration.LoadOrCreateConfiguration();
_workerQueue.AddProvider("Testsystem");
MulticastConfiguration mc = new MulticastConfiguration
{
LocalIPAddress = "192.168.0.15",
LocalPort = 0,
RemoteIPAddress = "233.233.233.233",
RemotePort = 43238,
MaxSegmentSize = 200,
ReceiveBufferSize = 8192,
SocketBufferSize = 64000,
IsConfigured = true
};
Console.WriteLine(mc);
MulticastReceiver mr = new MulticastReceiver(mc);
Console.WriteLine("Init");
mr.Initialize();
Console.WriteLine("Creating PDU Helper");
mr.NewCallListReady += CallListReadyToProcess;
mr.Receive();
int counter = 0;
while (true)
{
Console.WriteLine("Messages for Testsystem: {0}, Counter: {1}", _workerQueue.Count, counter);
Thread.Sleep(1000);
if (counter == 20)
break;
counter++;
}
Console.WriteLine("Press any Key to End!");
Console.ReadLine();
mr.Stop();
}
static void CallListReadyToProcess(object sender, EventArgs e)
{
MTPEventArgs test = e as MTPEventArgs;
Console.WriteLine("Received new Line: {0}", test.CallList);
CallListLine tempLine = new CallListLine
{
Provider = "Testsystem",
Data = test.CallList,
TimeStamp = DateTimeOffset.Now
};
_workerQueue.Enqueue(tempLine);
}
}