I'm trying to write a simple client to receive multicast data. I've tried many different iterations and none of them work. The environment that I am using is .netcore 2.2.2 and in a linux environment. I can see that the data is being sent to the proper interface via tcpdump but my client always gets stuck at the receive. I also have a program that was written in Java by a previous developer which properly receives data from interfaces below so I can confirm that the route does indeed work.
Attempt #1
mcastSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
IPAddress localIPAddr = IPAddress.Parse("10.51.254.2");
EndPoint localEP = (EndPoint)new IPEndPoint(localIPAddr, mcastPort);
mcastSocket.Bind(localEP);
mcastOption = new MulticastOption(mcastAddress, localIPAddr);
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
mcastOption);
EndPoint remoteEp = new IPEndPoint(mcastAddress, mcastPort);
// I have tried using (localIPAddr, mcastPort), (IPAddress.Any, 0),
// (localIPAddr, 0), (IPAddress.Any, mcastPort)
byte[] arr = new byte[4096];
Console.WriteLine("Socket setup");
var receivedBytes = mcastSocket.ReceiveFrom(arr, ref remoteEp );
Console.WriteLine("Got data");
Attempt#2
UdpClient client = new UdpClient();
client.ExclusiveAddressUse = false;
IPEndPoint localEp = new IPEndPoint(IPAddress.Parse("10.51.254.2"), 14382);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
client.Client.Bind(localEp);
client.JoinMulticastGroup(IPAddress.Parse("224.0.31.130"), IPAddress.Parse("10.51.254.2"));
Console.WriteLine("Listening this will never quit so you will need to ctrl-c it");
IPEndPoint remoteEp = new IPEndPoint(IPAddress.Parse("224.0.31.130"), 14382);
EndPoint remoteEndPoint = (EndPoint) new IPEndPoint(IPAddress.Any, 0);
while (true)
{
Byte[] data = client.Receive(ref remoteEndPoint);
Console.WriteLine("got data");
}
Any help would be greatly appreciated.
FIXED using the following code
try
{
mcastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress localIPAddr = IPAddress.Parse("10.51.254.2");
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, mcastPort);
mcastSocket.Bind(localEP);
MulticastOption option = new MulticastOption(mcastAddress, localIPAddr);
mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option);
EndPoint remoteEp = new IPEndPoint(localIPAddr, mcastPort);
byte[] arr = new byte[4096];
while (true)
{
var receivedBytes = mcastSocket.ReceiveFrom(arr, ref remoteEp);
Console.WriteLine($"Got data {receivedBytes}");
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Related
I know there are already many queries on this forum. I have searched and at the end I am stuck to this issue thats why I am asking it.
I have a number of devices which can communicate on UDP.
I want to query them for status update. This is my code.
List<IPAddress> iPAdd = new List<IPAddress>();
foreach (string s in ipaddress)
{
IPAddress ips = IPAddress.Parse(s);
iPAdd.Add(ips);
}
//The main socket on which the server listens to the clients
byte[] byteData = new byte[1024];
Byte[] dataToSend = new Byte[] { 0x8B, 0xB9, 0x00, 0x03, 0x05, 0x01, 0x09 };
try
{
serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
//Assign the any IP of the machine and listen on port number 1200
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Bind this address to the server
serverSocket.Bind(ipEndPoint);
foreach(IPAddress ip in iPAdd)
{
IPEndPoint ipe = new IPEndPoint(ip, 1024);
EndPoint e = (EndPoint)ipe;
eps.Add(e);
}
//Start sending data
foreach(EndPoint ep in eps)
{
serverSocket.BeginSendTo(dataToSend, 0, dataToSend.Length, SocketFlags.None, ep,
new AsyncCallback(OnSend), ep);
Thread.Sleep(50);
Receive(ep);
}
}
catch (Exception ex)
{
string mess = ex.Message;
}
receive method -
private void Receive(EndPoint ep)
{
Byte[] receiveBytes = new Byte[1024];
IPEndPoint localip = new IPEndPoint(IPAddress.Any, 1200);
UdpClient receivingUdpClient = new UdpClient(localip);
receivingUdpClient.Client.Receive(receiveBytes);
receivingUdpClient.Dispose();
}
Error I am receiving by receivingUdpClient is -
"A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"
What Am I doing wrong.? If I am completely wrong then also.. Any suggestions and advice are welcome
I got the way to do what I wanted to do.
Here is the code and explaination of what I was trying to do. Hope it help others.
MY task - Needed to create udp connection between multiple devices of same kind that receive query on 1024 and replied on 1200.
At the end I realized its simple as it is for single client. Now I am thinking how silly of me getting confused by these many options available.
Here is the code -
public byte[] serverSocket(String IPadd)
{
Socket serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Socket receiveClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
byte[] receivebytes = new byte[100] ;
try
{
byte[] dataToSend = new byte[] { 0x8B, 0xB9, 0x00, 0x03, 0x05, 0x01, 0x09 };
IPAddress iPAddress = IPAddress.Parse(IPadd);
int port = 1024;
IPEndPoint iPEnd = new IPEndPoint(iPAddress, port);
//Assign the any IP of the machine and listen on port number 1200
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1200);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 2000);
serverSocket.Bind(ipEndPoint);
EndPoint ep = (EndPoint)iPEnd;
serverSocket.SendTo(dataToSend, ep);
Thread.Sleep(1000);
serverSocket.Receive(receivebytes);
}
catch(Exception ex)
{
}
finally
{
serverSocket.Dispose();
}
return receivebytes;
}
String IPadd is the string from the list of ipaddresses that I got from database. So here what I am doing is - I am calling udp Connection and disposing it after receiving data so that I can use the same socket object for other IP address.
See its as simple as that.
And last but not the least, the guys on this forum.. Thank you very much because your suggestions gave me a different look to think of.
When I use "127.0.0.1" on the same computer, it works just fine. If I try to use the server's public ip address, it doesn't work (actually I get a socket error). If I make it ipaddress.any it doesn't give an error, but it doesn't work, either. I thought maybe it's because I'm on the same computer, so I put the server on my desktop and client on my laptop, and I connected my laptop to my phone's hotspot so the ipaddress is different. It still doesn't work. The message gets sent, but never received. What am I doing wrong?
struct DataPacket
{
public IPEndPoint destination;
public byte[] data;
public DataPacket(IPEndPoint destination, byte[] data)
{
this.destination = destination;
this.data = data;
}
}
AsyncPriorityQueue<DataPacket> queuedReceiveData = new AsyncPriorityQueue<DataPacket>(NetworkConstants.MAX_PLAYERS_PER_SERVER, false);
Socket sck;
IPEndPoint ipEndPoint;
bool listening = true;
bool processing = true;
void Start()
{
sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
#if SERVER
ipEndPoint = new IPEndPoint(IPAddress.Any, NetworkConstants.SERVER_PORT);
sck.Bind(ipEndPoint);
#else
ipEndPoint = new IPEndPoint(IPAddress.Parse(NetworkConstants.SERVER_IP), NetworkConstants.SERVER_PORT);
EndPoint ep = new IPEndPoint(IPAddress.Any, 0); // doesn't work at all
//EndPoint ep = new IPEndPoint(IPAddress.Parse(NetworkConstants.SERVER_IP), 0); // says requested address is not valid in its context
//EndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0); // works only on same computer
sck.Bind(ep);
#endif
new Thread(() => ListenForData()).Start();
new Thread(() => ProcessData()).Start();
#if !SERVER
SerializeCompact.BitStream bs = new SerializeCompact.BitStream();
bs.Write(Headers.Connect, minHeader, maxHeader);
SendData(bs.GetByteArray());
#endif
}
void OnDestroy()
{
listening = false;
processing = false;
sck.Close();
}
public void SendData(byte[] data)
{
var packet = queuedSendData.Dequeue();
sck.SendTo(data, 0, data.Length, SocketFlags.None, ipEndPoint);
print("message sent to server");
}
public void SendDataTo(byte[] data, IPEndPoint endPoint)
{
var packet = queuedSendData.Dequeue();
sck.SendTo(data, 0, data.Length, SocketFlags.None, endPoint);
print("message sent to client");
}
void ListenForData()
{
while (listening)
{
EndPoint endPoint = ipEndPoint;
byte[] buffer = new byte[1024];
int rec = sck.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref endPoint);
Array.Resize(ref buffer, rec);
queuedReceiveData.Enqueue(new DataPacket((IPEndPoint) endPoint, buffer), 0);
print("received message");
ProcessData(buffer);
}
}
void ProcessData()
{
while (processing)
{
var rcv = queuedReceiveData.Dequeue(); // blocks until an item can be dequeued
byte[] data = rcv.data;
IPEndPoint ep = rcv.destination;
// process data...
}
}
The following code sends a packet on port 15000:
int port = 15000;
UdpClient udp = new UdpClient();
//udp.EnableBroadcast = true; //This was suggested in a now deleted answer
IPEndPoint groupEP = new IPEndPoint(IPAddress.Broadcast, port);
string str4 = "I want to receive this!";
byte[] sendBytes4 = Encoding.ASCII.GetBytes(str4);
udp.Send(sendBytes4, sendBytes4.Length, groupEP);
udp.Close();
However, it's kind of useless if I can't then receive it on another computer. All I need is to send a command to another computer on the LAN, and for it to receive it and do something.
Without using a Pcap library, is there any way I can accomplish this? The computer my program is communicating with is Windows XP 32-bit, and the sending computer is Windows 7 64-bit, if it makes a difference. I've looked into various net send commands, but I can't figure them out.
I also have access to the computer (the XP one)'s local IP, by being able to physically type 'ipconfig' on it.
EDIT: Here's the Receive function I'm using, copied from somewhere:
public void ReceiveBroadcast(int port)
{
Debug.WriteLine("Trying to receive...");
UdpClient client = null;
try
{
client = new UdpClient(port);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
IPEndPoint server = new IPEndPoint(IPAddress.Broadcast, port);
byte[] packet = client.Receive(ref server);
Debug.WriteLine(Encoding.ASCII.GetString(packet));
}
I'm calling ReceiveBroadcast(15000) but there's no output at all.
Here is the simple version of Server and Client to send/receive UDP packets
Server
IPEndPoint ServerEndPoint= new IPEndPoint(IPAddress.Any,9050);
Socket WinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
WinSocket.Bind(ServerEndPoint);
Console.Write("Waiting for client");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)
EndPoint Remote = (EndPoint)(sender);
int recv = WinSocket.ReceiveFrom(data, ref Remote);
Console.WriteLine("Message received from {0}:", Remote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Client
IPEndPoint RemoteEndPoint= new IPEndPoint(
IPAddress.Parse("ServerHostName"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
Am trying to make a simple UDP application using C sharp,nothing sophisticated,connect,send some text,and receive it! but it keeps throwing this exception!
"An existing connection was forcibly closed by the remote host"!
The code :
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)sender;
data = new byte[1024];
int recv = server.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Message received from {0}:", tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Console.WriteLine("Stopping client");
server.Close();
thanks =)
You should tell the system that you are listening for UDP packets on port 9050 before you call Receive.
Add server.Bind(ipep); after Socket server = new Socket(...);
Have you tried checking that the IP address is valid and the port is not being used for something else?
Windows:
Start > Run > "cmd" > "ipconfig".
Try turning off your firewall software.
If you do not know the IP of the answering server, you better do:
recv = server.Receive(data);
Here is my suggetion to your code. You can use a do-while loop using a condition (in my example it is an infinite loop):
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.ReceiveTimeout = 10000; //1second timeout
int rslt = server.SendTo(data, data.Length, SocketFlags.None, ipep);
data = new byte[1024];
int recv = 0;
do
{
try
{
Console.WriteLine("Start time: " + DateTime.Now.ToString());
recv = server.Receive(data); //the code will be stoped hier untill the time out is passed
}
catch { }
} while (true); //carefoul! infinite loop!
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Console.WriteLine("Stopping client");
server.Close();
Here is my code
Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck.Bind(new IPEndPoint(IPAddress.Any, 0));
// Broadcast to find server
string msg = "Imlookingforaserver:" + udp_listen_port;
byte[] sendBytes4 = Encoding.ASCII.GetBytes(msg);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("255.255.255.255"), server_port);
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sck.SendTo(sendBytes4, groupEP);
//Wait response from server
Socket sck2 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck2.Bind(new IPEndPoint(IPAddress.Any, udp_listen_port));
byte[] buffer = new byte[128];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udp_listen_port);
sck2.ReceiveFrom(buffer, ref remoteEndPoint); //<<< I never pass this line
I use above code to try find a server. First I broadcast a message and then I wait for a response from the server.
A test I made with the server written in C++ and running in Windows Vista, client written in C# and run on the same machine with server.
Problem is: The server can receive message which client broadcast, but client can not receive anything from server.
I try to write a client with C++ and it work like a charm, I think my problem is in C# client.
I would start listening on that port before you broadcast. You're using UDP which is connectionless so you could be missing your packet.
Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck.Bind(new IPEndPoint(IPAddress.Any, 0));
//Wait response from server
Socket sck2 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck2.Bind(new IPEndPoint(IPAddress.Any, udp_listen_port));
byte[] buffer = new byte[128];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udp_listen_port);
// Broadcast to find server
string msg = "Imlookingforaserver:" + udp_listen_port;
byte[] sendBytes4 = Encoding.ASCII.GetBytes(msg);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("255.255.255.255"), server_port);
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sck.SendTo(sendBytes4, groupEP);
sck2.ReceiveFrom(buffer, ref remoteEndPoint);