Reputation:
In my adaption of a few multicast tutorials, I changed my method of sending packets.
In my case, I create a queue of packets of size bytes[1024]
, after which it is sent via Socket.Send()
over all online network adapters
Problem:
When sending, another method called receiveMessage()
is running on a separate thread. Using Socket.Bind()
, it captures packets, but only 1 packet is captured.
Am I doing too much processing thus delaying (and losing) the packets received?
UPDATE
I am considering adding a queue for incoming packets, thus 1 threads captures and stores, the second processes the packets.
SendMethod
Socket _listener_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
foreach (IPAddress localIP in Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
//handle image and files
_listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_MultiIP, localIP));
_listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 1);
_listener_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_listener_socket.MulticastLoopback = true;
_listener_socket.Connect(new IPEndPoint(_MultiIP, _PORT));
int count = MSGS_TO_SEND.Count;
while (count > 0)
{
count--;
byte[] temp = (byte[])(MSGS_TO_SEND.Dequeue());
_listener_socket.Send(temp, _BYTE_BUFFER_SIZE, SocketFlags.None);
MSGS_TO_SEND.Enqueue(temp);
}
//----------------------------------------------
//-------------------SEND DATA------------------
//----------------------------------------------
}
_listener_socket.Close();
Receive method
//initialise multicast group and bind to interface
Socket _sender_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _PORT);
_sender_socket.Bind(ipep);
IPAddress localip = _MultiIP;
_sender_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(localip, IPAddress.Any));
//{
while (_sender_socket.IsBound && !bStop)
{
byte[] b = new byte[_BYTE_BUFFER_SIZE];
_sender_socket.Receive(b);
char[] chars = new char[_BYTE_BUFFER_SIZE];
System.Buffer.BlockCopy(b, 0, chars, 0, b.Length);
string _message = new string(chars).Trim();
string ip = _message.Substring(0, _message.IndexOf("~"));
_message = _message.Remove(0, _message.IndexOf("~") + 1);
string _flag = _message.Substring(0, _message.IndexOf("~"));
_message = _message.Remove(0, _message.IndexOf("~") + 1);
_message = _message.Replace("\0", string.Empty);
ip = "1.0";
icount++;
handleData(ip, _flag, _message);
}
Upvotes: 8
Views: 726
Reputation: 372
The sender doesn't have to bind or add membership. Any datagram socket can send to a multicast address. The receiver needs to add membership to the multicast address. The sender and receiver also need to agree upon the port (receiver should be bound to the port.)
Your Multicast Options in each example have the arguments reversed.
The sockets already have buffering from the kernel, so you don't need to complicate your code with message queues.
Upvotes: 0
Reputation: 953
If you wan't to try, here is a fully working example: https://github.com/efaruk/playground/tree/master/Multicasting
You can use those re-usable components (MulticastSender
, MulticastReceiver
,) in your project if you whish...
Upvotes: 1