I have written a multicast client application for PC and for winCE
device. These applications are deployed on a PC and a CE device
respectively connected to the network by the same switch.
The Server application is deployed on the same switch on a PC. The
server sends a multicast message to the 2 Clients (on PC and on CE
Device). The PC Client receives the message correctly. But the CE
Device application does not receive the message..
Code for CE Client and PC Client is the same. The same Socket APIs
(supported by the Full and Compact Frameworks) are used. These APIs
(like socket.bind()) do not throw any exceptions.
Following is the code for the CE Client..
Does anything else need to be done ??
Thanks.
Shantanu..
using System;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TestClientCEDOS
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class MultiCastClient
{
private static IPAddress mcastAddress;
private static IPAddress localAddress;
private static int mcastPort;
private static Socket mcastSocket;
private static MulticastOption mcastOption;
/// <summary>
/// The main entry point for the application.
/// </summary>
// static void Main(string[] args)
// {
// //
// // TODO: Add code to start application here
// //
// }
private static void MulticastOptionProperties()
{
Console.WriteLine("Current multicast group is:
" +
mcastOption.Group);
Console.WriteLine("Current multicast local
address is: " +
mcastOption.LocalAddress);
}
private static void StartMulticast()
{
try
{
mcastSocket = new
Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
Console.Write("Enter the local IP
address: ");
//IPAddress localIPAddr =
IPAddress.Parse(Console.ReadLine());
IPAddress localIPAddr = localAddress;
EndPoint localEP = (EndPoint)new
IPEndPoint(localIPAddr,
mcastPort);
mcastSocket.Bind(localEP);
// Define a MulticastOption object
specifying the multicast group
// address and the local IPAddress.
// The multicast group address is the
same as the address used by
the server.
mcastOption = new
MulticastOption(mcastAddress, localIPAddr);
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership, mcastOption);
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastTimeToLive, 255);
}
catch (SocketException se)
{
Console.WriteLine(se.ToString());
Console.WriteLine(se.NativeErrorCode.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveBroadcastMessages()
{
bool done = false;
byte[] bytes = new Byte[100];
IPEndPoint groupEP = new
IPEndPoint(mcastAddress, mcastPort);
EndPoint remoteEP = (EndPoint) new
IPEndPoint(IPAddress.Any,0);
try
{
while (!done)
{
Console.WriteLine("Waiting for
multicast packets.......");
Console.WriteLine("Enter ^C to
terminate.");
mcastSocket.ReceiveFrom(bytes,
ref remoteEP);
Console.WriteLine("Received
broadcast from {0} :\n {1}\n",
groupEP.ToString(),
Encoding.ASCII.GetString(bytes,0,bytes.Length));
}
mcastSocket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
//[STAThread]
public static void Main(String[] args)
{
// Initialize the multicast address group and
multicast port.
// Both address and port are selected from the
allowed sets as
// defined in the related RFC documents. These
are the same
// as the values used by the sender.
String IPLocal = args[0];
String IPGroup = args[1];
mcastAddress = IPAddress.Parse(IPGroup);
localAddress = IPAddress.Parse(IPLocal);
mcastPort = 11000;
// Start a multicast group.
StartMulticast();
// Display MulticastOption properties.
//MulticastOptionProperties();
// Receive broadcast messages.
ReceiveBroadcastMessages();
}
}
The Server code is as follows :
The Server code is as follows :
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
namespace MultiCastServer
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class MultiCastServer
{
static IPAddress mcastAddress;
static IPAddress localAddress;
static int mcastPort;
static Socket mcastSocket;
static void JoinMulticastGroup()
{
try
{
// Create a multicast socket.
mcastSocket = new
Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
// Get the local IP address used by the listener
and the sender to
// exchange multicast messages.
IPAddress localIPAddr = localAddress;
// Create an IPEndPoint object.
IPEndPoint IPlocal = new IPEndPoint(localIPAddr,
0);
// Bind this endpoint to the multicast socket.
mcastSocket.Bind(IPlocal);
// Define a MulticastOption object specifying the
multicast group
// address and the local IP address.
// The multicast group address is the same as the
address used by the listener.
MulticastOption mcastOption;
mcastOption = new MulticastOption(mcastAddress,
localIPAddr);
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership, mcastOption);
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastTimeToLive, 255);
}
catch (Exception e)
{
Console.WriteLine("\n" + e.ToString());
}
}
static void BroadcastMessage(string message)
{
IPEndPoint endPoint;
try
{
//Send multicast packets to the listener.
endPoint = new IPEndPoint(mcastAddress,mcastPort);
mcastSocket.SendTo(ASCIIEncoding.ASCII.GetBytes(message), endPoint);
Console.WriteLine("Multicast data sent.....");
}
catch (Exception e)
{
Console.WriteLine("\n" + e.ToString());
}
//mcastSocket.Close();
}
[STAThread]
static void Main(string[] args)
{
bool done = false;
// Initialize the multicast address group and multicast
port.
// Both address and port are selected from the allowed
sets as
// defined in the related RFC documents. These are the
same
// as the values used by the sender.
//mcastAddress = IPAddress.Parse("10.10.0.196");
localAddress = IPAddress.Parse(args[0]);
mcastAddress = IPAddress.Parse(args[1]);
mcastPort = 11000;
// Join the listener multicast group.
JoinMulticastGroup();
// Broadcast the message to the listener.
BroadcastMessage("Hello multicast listener.");
}
}
}
NonUnicast Packets Received is the same before and after the server
sends the multicast message..
Does this help?
Shantanu..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138172139.1...@f14g2000cwb.googlegroups.com...
The connection is via an Ethernet LAN.. Also, the CE Device is using
DHCP for IP configuration etc..
Thanks..
Shantanu..
PS: I did not know that you can post to more than I news group at the
same time.. Sorry for the separate multiple posts.. Will post together
in the future..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138314334.0...@g47g2000cwa.googlegroups.com...
Are u using the same code that I have used?? I want to eliminate
anything at the software end..
Thanks..
Shantanu..
PS: The PC Client on the same LAN is receiving the multicast messages
properly.. This PC Client has the same code as the CE Client.. Does
anything different have to be done on the CE Client??
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138316266.5...@g43g2000cwa.googlegroups.com...
How do you check if the NIC driver (on the CE Device) supports IP
multicast and if it is 'turned on' ?? ie check that the NIC is not
filtering out the multicast messages.. The Ethernet chip that the
Device is using, does support multicasting. But I do not know how to
check that it is 'turned on'.
Thanks.
Shantanu..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138343237.8...@g44g2000cwa.googlegroups.com...
I checked that the Socket.bind() method is not Binding.. It is not
throwing any exceptions but has an invalid (negative) value in the
LocalEndPoint m_Address field. This means that the bind is not
executing successfully. Even though the correct local address is
supplied as the end point.
Any ideas?? Thanks..
Thanks.
Shantanu..
PS:
Also, I checked with the ARM terminal vendors and the Ethernet chip
they are using in the device supports multicasting.. I checked the
datasheet for the Ethernet chip and it does support multicasting..
Also, the driver is supposed to support it too..
How do one turn on this feature, if it is turned off??
Also, now,
the netstat -e (on the CE Device) shows that the
"NonUnicast Packets Received" INCREASES before and after the server
sends the multicast message.. Meaning that the Server packets are being
received..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138768340....@g14g2000cwa.googlegroups.com...
USING UdpClient FOR IP MULTICASTING :
Now, I am trying to use the .NET UdpClient class for creating the
client/server for the IP multicasting.
The CE Client is executing properly on the CE Device and is waiting at
Receive(), as it should..
However, when I run the Server and it tries to execute
JoinMulticastGroup(), it throws a socket exception "An invalid argument
was supplied" with error code 10022. I looked up the Windows Sockets
Error Codes which said the following about this error :
----------------------------------
WSAEINVAL
10022
Invalid argument.
Some invalid argument was supplied (for example, specifying an invalid
level to the setsockopt function). In some instances, it also refers to
the current state of the socket-for instance, calling accept on a
socket that is not listening.
---------------------------------
However, the arguments (multicastaddress and TTL) are correct..
Any ideas why this error code is coming up..
Thanks..
Shantanu..
Following is the Server code :
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
public class Multi_srv
{
public static void Main()
{
UdpClient udpclient=new UdpClient();
try
{
Console.WriteLine("Starting Server...");
string myip="10.10.0.196";
IPAddress multicastaddress = IPAddress.Parse("224.5.6.7");
udpclient.JoinMulticastGroup(multicastaddress, 1);
IPEndPoint remoteep = new IPEndPoint( multicastaddress, 11000 );
Byte [] buffer = null;
Encoding enc = Encoding.Unicode;
while(true)
{
Console.WriteLine("Enter message to be sent to client : ");
string str=Console.ReadLine();
buffer=enc.GetBytes(str.ToCharArray());
udpclient.Send(buffer, buffer.Length,remoteep);
Console.WriteLine("Message sent...");
}
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
Console.WriteLine(se.NativeErrorCode.ToString());
Console.WriteLine(se.StackTrace);
udpclient.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
Following is the CE Client code :
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
public class Muticast_cli
{
public static void Main()
{
Console.WriteLine("Starting Client...");
UdpClient udpclient = new UdpClient(11000);
IPAddress multicastaddress=IPAddress.Parse("224.5.6.7");
udpclient.JoinMulticastGroup(multicastaddress, 1);
IPEndPoint remote=null;
Encoding enc = Encoding.Unicode;
while(true)
{
Console.WriteLine("Start receiving...");
Console.WriteLine("Press ^C to Terminate...");
Byte[] data =udpclient.Receive(ref remote);
String strData = enc.GetString(data, 0, data.Length);
Console.WriteLine(strData);
}
}
}
I found that initializing the UdpClient with a port no. solved the
earlier exception in Server's JoinMulticastGroup()..
UdpClient udpclient=new UdpClient(11000);
Now, the
udpclient.Send(buffer, buffer.Length,remoteep);
is executing properly and is returning the correct no of bytes sent as
the return value, as it is supposed to..
The Server is working properly..
However, the CE Client is not receiving anything, even though it is
waiting at the Receive()..
Also, the netstat -e (on the CE Device) shows that the
"NonUnicast Packets Received" is INCREASING STEADILY from the time the
Device is switched on (Nothing to do with the Server send).. Meaning
that the NonUnicast packets are being received.. Seems like the Device
is receiving NonUnicast packets being sent from somewhere..
Any advice??.. Now, I have tried UdpClient also..
Thanks..
Shantanu..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1138859154....@g49g2000cwa.googlegroups.com...
As u had advised, I moved away from .NET and built an embedded VC++
Multicast client.. All, the SOCKET APIs (like bind, setsockopt etc.. )
execute without incident (no errors).. The client comes to recvfrom API
and waits for multicast messages..
Also, I found this article in MSDN regards IP Multicasting and CE
Registry:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcetcpip/html/cmconparametersconfigurableusingregistryeditor.asp
Accordingly, I have also created a DWORD Value in the Registry called
IGMPLevel under HKEY_LOCAL_MACHINE\Comm\Tcpip\Parms and set the value
of this to 2.
Still the client is not receiving any multicast messages.. The PC
Client on the same router is receiving the messages properly..
The .NET C# client ( as I have explained earlier) does not execute the
bind() properly as after the bind there is a negative value in the
LocalEndPoint/m_address field of the Socket..
Thanks..
Shantanu..
CODE FOR Embedded VC++ Client.. This is from MSDN and so it should
work..
//--------------------------------------------------------------------------------
// TestVCPPApp.cpp : Defines the entry point for the application.
#include "stdafx.h"
#include <winsock.h>
//#include <winsock2.h>
#define RECV_IP_ADDR "224.5.6.7"
#define DEST_PORT 11000
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
int index = 0, // Integer index
iRecvLen; // Length of recv_sin
char szMessageA[100]; // ASCII string
TCHAR szMessageW[100]; // Unicode string
TCHAR szError[100]; // Error message string
SOCKET Sock = INVALID_SOCKET; // Datagram window socket
struct ip_mreq mreq; // Used in adding or dropping
// multicasting addresses
SOCKADDR_IN local_sin, // Local socket's address
recv_sin; // Holds the source address on
// recvfrom function returns
WSADATA WSAData; // Contains details of the
// Winsock implementation
// Initialize Winsock.
if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
wsprintf (szError, TEXT("WSAStartup failed! Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
// Create a datagram socket, Sock.
if ((Sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Allocating socket failed! Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
return FALSE;
}
// Fill out the local socket's address information.
local_sin.sin_family = AF_INET;
local_sin.sin_port = htons (DEST_PORT);
local_sin.sin_addr.s_addr = htonl (INADDR_ANY);
// Associate the local address with Sock.
if (bind (Sock,
(struct sockaddr FAR *) &local_sin,
sizeof (local_sin)) == SOCKET_ERROR)
{
wsprintf (szError, TEXT("Binding socket failed! Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (Sock);
return FALSE;
}
// Join the multicast group from which to receive datagrams.
mreq.imr_multiaddr.s_addr = inet_addr (RECV_IP_ADDR);
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt (Sock,
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
(char FAR *)&mreq,
sizeof (mreq)) == SOCKET_ERROR)
{
wsprintf (szError, TEXT("setsockopt failed! Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (Sock);
return FALSE;
}
iRecvLen = sizeof (recv_sin);
wsprintf (szError, TEXT("Starting Receive... : %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
// Receive data from the multicasting group server.
if (recvfrom (Sock,
szMessageA,
100,
0,
(struct sockaddr FAR *) &recv_sin,
&iRecvLen) == SOCKET_ERROR)
{
wsprintf (szError, TEXT("recvfrom failed! Error: %d"),
WSAGetLastError ());
MessageBox (NULL, szError, TEXT("Error"), MB_OK);
closesocket (Sock);
return FALSE;
}
else
{
// Convert the ASCII string to a Unicode string.
for (index = 0; index <= sizeof (szMessageA); index++)
szMessageW[index] = szMessageA[index];
MessageBox (NULL, szMessageW, TEXT("Info"), MB_OK);
}
// Disable receiving on Sock before closing it.
shutdown (Sock, 0x00);
// Close Sock.
closesocket (Sock);
WSACleanup ();
return TRUE;
// return 0;
}
//--------------------------------------------------------------------------------
I used the Remote Performance Monitor to monitor the UDP data on the CE
Device and it can be noted that :
CE UDP Statistics
"Total Datagrams/Sec" - Specifies the number of datagrams transmitted
or received per second.- varies from 0 to 7 per sec.
"Number of Addresses" - Specifies the number of entries in the UDP
listener table. - This value is constant at 3.. When I run the eVC++
multicast client and the bind() method is executed this value increases
by 1 to 4. When I shut the client app, this value decreases by 1 back
to 3..
Does this help??
Thanks..
Shantanu..
Check the following in your C code:
1. You are creating a datagram, not a stream socket. SOCKET_DGRAM.
2. You are binding the socket using a well-known fixed port number that the
mcast sender is aware of and you are properly using htons() to get the byte
order.
local_sin.sin_port = htons (DEST_PORT);
3. You are allowing any of the device's IP addresses to be associated with
the socket:
local_sin.sin_addr.s_addr = htonl (INADDR_ANY);
4. You are properly joining the multicast group that your sender is a member
of:
mreq.imr_multiaddr.s_addr = inet_addr( joinIPs );
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt (Sock,
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
(char FAR *)&mreq,
sizeof (mreq)) == SOCKET_ERROR)
In this case joinIPs is the *ASCII* string representing the group to be
joined. You may not be getting the group name this way, but make *sure*
that you are using ASCII strings, not Unicode.
5. You might as well set the TTL option on the socket that you're using,
rather than in the registry:
// Set the Time-to-Live of the multicast.
int iOptVal = 2;
if (setsockopt (Sock,
IPPROTO_IP,
IP_MULTICAST_TTL,
(char FAR *)&iOptVal,
sizeof (int)) == SOCKET_ERROR)
One of these might get you to the problem...
What multicast group are you joining?
Paul T.
<shanta...@hotmail.com> wrote in message
news:1139190295....@g44g2000cwa.googlegroups.com...
The multicast group that I am using is 224.5.6.7 and the port is
11000.. These are the same values being used by the PC Client too on
the same router.. And it receives multicast messages from the PC
Server..
I went through ur checklist very carefully and ran the eVC++ CE
Client.. However, no multicast messages were received..
Also, I used the IP Helper API GetUdpTable(). When this is called
before the bind, MIB_UDPTABLE->dwNumEntries value is 3.. After the
bind, this value changes to 4.. However, the MIB_UDPTABLE->table
returned, contains only one entry (before and after the bind)
dwLocalAddress 0
swLocalPort 13568
There is no other entry in this table.. Before and after the bind()..
This is not an entry which the client has put in.. Even though the
dwNumEntries goes up by 1 from 3 to 4..
Shantanu..
Paul T.
<shanta...@hotmail.com> wrote in message
news:1139269423....@g43g2000cwa.googlegroups.com...
Paul T.
"Paul G. Tobey [eMVP]" <ptobey no spam AT no instrument no spam DOT com>
wrote in message news:OJQGHRBL...@TK2MSFTNGP11.phx.gbl...
Bingo man..
It worked like a charm.. 224.0.0.4.. The CE .NET (C#) Client is
receiving messages..
Thanks for all your efforts.. Really appreciate it..
Shantanu..