I'm trying to send a multicast packet on all my network interfaces(2 LAN, one wifi). I initialy followed this tutorial.
The problem I encounter, is that it seems that the packet seems to be with only one of my IP address.
Here is my current code.
private static void SendOnAllCards(int port, String address)
{
using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse(address)));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(address), port);
mSendSocket.Connect(ipep);
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
}
}
I tried to do it manually:
private static void SendOnAllCards(int port, string remoteAddressSrc)
{
foreach (IPAddress remoteAddress in Dns.GetHostAddresses(Dns.GetHostName()).Where(i=>i.AddressFamily == AddressFamily.InterNetwork))
{
using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse(remoteAddressSrc)));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
IPEndPoint ipep = new IPEndPoint(remoteAddress, port);
mSendSocket.Connect(ipep);
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
}
}
}
This works, but it implies I've to create as many socket that I've IP(in this sample I create them on each send, but it's just a test), and I don't like the way I've to obtain all my IPs.
So what is the right way to do this?
Edit second bonus question: Why is this working when I specify the local ip in the Connect, which specify the remote address, but doesn't on the Bind?
Seems that we have to iterate on network interfaces, make a Bind on the local IP and do a Send*To* call:
public void SendTestMessage()
{
foreach (IPAddress localIp in
Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
IPAddress ipToUse = localIp;
using (var mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(_multicastIp, localIp));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.MulticastLoopback = true;
mSendSocket.Bind(new IPEndPoint(ipToUse, _port));
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
var ipep = new IPEndPoint(_multicastIp, _port);
mSendSocket.SendTo(bytes, ipep);
}
}
}
You could find the network adapters using the WMI class Win32_NetworkAdapter. You might have to refine the results that querying for instances of that brings, because there are many 'virtual adapters' created by both windows and third party software.
I wrote up a quick posh script to retreive the adapters using WMI. This should only display adapaters that have IP addresses. This is just to show the WMI information that you could query to retreive the activate adapeters.
$networkadapters = #(Get-CimInstance -ClassName Win32_NetworkAdapter -Property *)
$networkadapters_configs = #($networkadapters | Get-CimAssociatedInstance -ResultClassName Win32_NetworkAdapterConfiguration)
0..($networkadapters.Length-1) | %{
if($networkadapters_configs[$_].IPAddress -gt '') {
Write-Output "Adapter #$($_)"
Write-Output $networkadapters[$_]
Write-Output "Config #$($_)"
Write-Output $networkadapters_configs[$_]
}
}
Related
I am trying to develop a C# UTP server in order to send a list of string sList. This is continuously filled by another thread. My aspected software behavior is to get a client on the network and send each information.
Here the method:
internal static void MyUDPSocket()
{
byte[] data = new byte[1024];
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 9050);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(ip);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 9050);
EndPoint Remote = (EndPoint)(sender);
while (true)
{
if (sList.Count > 0)
{
try
{
data = Encoding.ASCII.GetBytes(sList[0]);
socket.SendTo(data, data.Length, SocketFlags.None, Remote);
sList.RemoveAt(0);
}
catch (FormatException e) { }
catch (System.ArgumentNullException en) { }
}
}
}
Anyway, when I launch the software, C# return an Exception (System.Net.Sockets.SocketException) on socket.SendTo(data, data.Length, SocketFlags.None, Remote) and it say that there is not a required address in the context.
You are creating a destination address with INADDR_ANY, with a port of 0. You can't do that.
I have an udp client server source on C# and now I have a problem: I test my source on localhost but it doesn't receive on long way connections for example a VPS to a client.
Client:
private static void StartListener()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (!done)
{
byte[] bytes = listener.Receive(ref groupEP);
Thread.Sleep(100);
byte[] dcbufresponse = new byte[512];
dcbufresponse = Encoding.ASCII.GetBytes("0xc00901");
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ipaddresssv), 9052);
s.SendTo(dcbufresponse, dcbufresponse.Length, SocketFlags.None, ipep);
done = true;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
listener.Close();
}
}
Server :
private static Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private static IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ipnow), 9052);
s.SendTo(dcbuf, dcbuf.Length, SocketFlags.None, ipep);
Console.WriteLine("sended");
sended.Add(ipnow);
try
{
listener.Client.ReceiveTimeout = 5000;
byte[] bytes = listener.Receive(ref groupEP);
string dcresponse = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
Console.WriteLine(dcresponse);
}
Problem is this : client doesn't receive anything and client can not send to server after receiving ...
Edit :
My Serve Have Two Ip Address !
and i thinking that i must bind once of my two ip address to my udp client :-?
do you think that its work ?
I have a program that multiple clients would be able to connect to a server using a socket:
private void performConnect()
{
while (true)
{
if (myList.Pending())
{
thrd = thrd + 1;
tcpClient = myList.AcceptTcpClient();
IPEndPoint ipEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
string clientIP = ipEndPoint.Address.ToString();
nStream[thrd] = tcpClient.GetStream();
currentMsg = "\n New IP client found :" + clientIP;
recieve[thrd].Start();
this.Invoke(new rcvData(addNotification));
try
{
addToIPList(clientIP);
}
catch (InvalidOperationException exp)
{
Console.Error.WriteLine(exp.Message);
}
Thread.Sleep(1000);
}
}
}
then the server could send data (chat messages) to a chosen client, using this code.
private void sendData(String data)
{
IPAddress ipep =IPAddress.Parse(comboBox1.SelectedItem.ToString());
Socket server = new Socket(AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipept = new IPEndPoint( ipep, hostPort);
NetworkStream nStream = tcpClient.GetStream();
ASCIIEncoding asciidata = new ASCIIEncoding();
byte[] buffer = asciidata.GetBytes(data);
if (nStream.CanWrite)
{
nStream.Write(buffer, 0, buffer.Length);
nStream.Flush();
}
}
the problem is that whatever IP i choose from the combo box, the message i send would always be directed/sent to the last IP that connected to the server.. Please somebody pinpoint my error! all help would be appreciated.
Look at those lines:
IPAddress ipep =IPAddress.Parse(comboBox1.SelectedItem.ToString());
Socket server = new Socket(AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipept = new IPEndPoint( ipep, hostPort);
NetworkStream nStream = tcpClient.GetStream();
You are creating a new socket but you are sending the data to the socket stored in the variable tcpClient that is global (since it was not defined in the method), thus totally ignoring the IPEndPoint parsed from the combobox.
You should not create a new socket in order to send data to the clients. Instead, store all clients in a collection and retrieve the appropriate one based on the input of the combobox.
I'm trying to send and receive data to a specific endpoint with local port 50177. Send data does very good, but when the program tries to receive data it can't receive any. When I sniff the network with Wireshark I see that server sent data to me. I know that I can't have 2 UdpClient on one port at the same time.
Can any one help me?
UdpClient udpClient2 = new UdpClient(50177);
IPEndPoint Ip2 = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 1005);
udpClient2.Send(peerto255, peerto255.Length, Ip2);
IPEndPoint Ip = new IPEndPoint(IPAddress.Parse("10.10.240.1"), 1005);
var dgram = udpClient2.Receive(ref Ip);
You can absolutely have two UdpClient on one port but you need to set socket options before you bind it to an endpoint.
private static void SendAndReceive()
{
IPEndPoint ep1 = new IPEndPoint(IPAddress.Any, 1234);
ThreadPool.QueueUserWorkItem(delegate
{
UdpClient receiveClient = new UdpClient();
receiveClient.ExclusiveAddressUse = false;
receiveClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiveClient.Client.Bind(ep1);
byte[] buffer = receiveClient.Receive(ref ep1);
});
UdpClient sendClient = new UdpClient();
sendClient.ExclusiveAddressUse = false;
sendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPEndPoint ep2 = new IPEndPoint(IPAddress.Parse("X.Y.Z.W"), 1234);
sendClient.Client.Bind(ep1);
sendClient.Send(new byte[] { ... }, sizeOfBuffer, ep2);
}
Use the same IPEndPoint for receiving that you used for sending.
UdpClient udpClient2 = new UdpClient(50177);
IPEndPoint Ip2 = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 1005);
udpClient2.Send(peerto255, peerto255.Length, Ip2);
var dgram = udpClient2.Receive(ref Ip2);
As kind of a followup to this question I've gotten a solution working on my local machine, but not on a machine on the network.
I don't know too much about sockets other than that basics, so bear with me. The goal is for a client to look for a server on a local network, and this is the result of some cut/paste/edit code.
This is the client code:
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10294);
byte[] data = new byte[1024];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);
string welcome = "What's your IP?";
data = Encoding.ASCII.GetBytes(welcome);
client.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint server = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)server;
data = new byte[1024];
int recv = client.ReceiveFrom(data, ref tmpRemote);
this.IP.Text = ((IPEndPoint)tmpRemote).Address.ToString(); //set textbox
this.Port.Text = Encoding.ASCII.GetString(data, 0, recv); //set textbox
client.Close();
}
This is the server code:
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 10294);
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
newsock.Bind(ipep);
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any,IPAddress.Parse("127.0.0.1")));
while (true)
{
Console.WriteLine("Waiting for a client...");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)(sender);
data = new byte[1024];
recv = newsock.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Message received from {0}:", tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
string welcome = "7010";
data = Encoding.ASCII.GetBytes(welcome);
newsock.SendTo(data, data.Length, SocketFlags.None, tmpRemote);
}
It works find on my local machine (both server and client) but when I try another machine on the same network I get "An existing connection was forcibly closed by the remote host"
I realize I need to add a lot of try/catch but I'm just trying to get a handle on how this works first.
I have to start by saying that I know nothing about C#, but...
Looking at the definition of the ipep in the client code, it looks like you're trying to send your data to yourself, rather than broadcast it (as has been suggested in your other question). The thing that caught my attention was that "127.0.0.1" is the address of "localhost".
That would explain why it works nicely when you're running both the client and server on the one machine, as it will be sending to itself.
I would expect that correct endpoint would be for a broadcast address (eg. "255.255.255.255") - although you could also choose the broadcast address of the local network that you're on, depending on how widely you wish to broadcast.
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10294);
Should become:
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 10294);
And
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any, IPAddress.Parse("127.0.0.1")));
Should Become
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any, IPAddress.Parse("255.255.255.255")));
I think.
OK, this doesn't work, so something's still wrong.