How do you get the IP of the sender of a Multicast UDP packet? The current code is setup in a synchronous/blocking manner (see note below). Here is the code:
private void receive()
{
string mcastGroup = SetMcastGroup();
s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.EnableBroadcast = true;
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 5000);
s.Bind(ipep);
IPAddress ip = IPAddress.Parse(mcastGroup);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
while (true)
{
try
{
byte[] b = new byte[4096];
s.Receive(b);
string str = Encoding.ASCII.GetString(b, 0, b.Length);
//this.SetText(ipep.Address + ": " + str.Trim());
this.SetText(senderIP() + ": " + str.Trim());
}
catch{}
}
}
Note: This question comes from chat, as such is not my code. I am only asking because I understand the problem.
Since you are using UDP you don't establish a connection with the remote endpoint (unlike TCP where you would have one socket per connection). Therefore you must get the address of the remote endpoint when you receive the datagram. To do this call receiveFrom instead of receive()
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.receivefrom.aspx
Related
I want to ask if it s possible to get the IpAddress from the ping host. So if someone pings my Computer I know his IpAddress. My Code Looks like this :
while (true)
{
Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
icmpListener.Bind(new IPEndPoint(IPAddress.Parse("564.89.556.5"), 0));
icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 });
byte[] buffer = new byte[4096];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
int bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
string text = "ICMPListener received " + bytesRead + " from " + remoteEndPoint;
Console.WriteLine(text);
}
After the Code Ran and someone pings me i know wich ip was pingd put not the one from the host of the ping. Thanks for the awnsers.
Try:
var ip = icmpListener.RemoteEndPoint;
If you are using a connection-oriented protocol, the RemoteEndPoint property gets the EndPoint that contains the remote IP address and port number to which the Socket is connected. If you are using a connectionless protocol, RemoteEndPoint contains the default remote IP address and port number with which the Socket will communicate. You must cast this EndPoint to an IPEndPoint before retrieving any information. You can then call the IPEndPoint.Address method to retrieve the remote IPAddress, and the IPEndPoint.Port method to retrieve the remote port number.
When using cmd to ping a machine (ping 127.0.0.1), you are pinging that maching with the default port of 80
Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
icmpListener.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80));
icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 });
while (true)
{
byte[] buffer = new byte[4096];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
int bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
Console.WriteLine("ICMPListener received " + bytesRead + " from " + remoteEndPoint);
}
Before you do anything, Open CMD as Administrator then type the following command: netsh advfirewall firewall add rule name="All ICMP v4" dir=in action=allow protocol=icmpv4:any,any This will allow the firewall rule to allow ICMP Port Unreachable packets to be received.
And Don't Forget To Run the C# program as Administrator
I have found this piece of code on the internet: it does not open a server listening on port 11000, as I hoped.
What can be the problem? I normally code in Delphi, so I am little lost. I have made a corresponding client in Delphi, which works.
I am using demo version of C# 2015.
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
// Start listening for connections.
while (true)
{
//Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("#") > -1)
{
break;
}
}
// Show the data on the console.
//Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
//Console.WriteLine("\nPress ENTER to continue...");
//Console.Read();
}
The problem might be here: Whats the IP address of ipHostInfo.AddressList[0] ? It might be the loop-back. I never restrict my server endpoint to an ip-adress unless I need to, but then I will specify it in a configfile.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 11000);
As per Jeroen's answer, encountered per .NET's Synchronous Server Socket Example. When listening/connecting to localhost, one should rather use
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
instead of
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
Thanks for feedback. I found som other, older code:
TcpListener serverSocket = new TcpListener(11000);
that does the job. I know it is depreciated, but it works, actually.
I'm using C# to create a client-server network. I created client successfully but i have an issue with the server. When i broadcast a message to the server it's supposed to send it to other clients as well. The problem is that the server too gets the message then it thinks it's another message and it creates an infinite loop that sends the same message over and over again. Can I broadcast excluding the server?
public void serverThread()
{
while (true)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udpClient_rec.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
if (returnData.StartsWith("broad"))
{
UdpClient udpClient_send = new UdpClient();
IPEndPoint RemoteIpEndPoint1 = new IPEndPoint(IPAddress.Broadcast, 8400);
//can i use something else here instead of broadcast to send it to everyone except myself(server)?
udpClient_send.EnableBroadcast = true;
udpClient_send.Send(receiveBytes, receiveBytes.Length, RemoteIpEndPoint1);
udpClient_send.Close();
}
this.SetText(RemoteIpEndPoint.Address.ToString() + ": " + returnData.ToString());
this.SetText2(RemoteIpEndPoint.Address.ToString());
}
}
For some reason I am having a hard time sending and receiving data from the same socket. Anyways here is my client code:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening (testing localy)
client.Connect(ep);
// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);
// then receive data
var receivedData = client.Receive(ref ep); // Exception: An existing connection was forcibly closed by the remote host
Basically I want to create a protocol where I send a udp packet and then I expect a response. Just like the HTTP protocol for every request there is a response. This code works if the server is on a different computer. There might be the case where the server and client are on the same computer though.
Here is the server:
UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);
while (true)
{
var groupEP = new IPEndPoint(IPAddress.Any, 11000); // listen on any port
var data = udpServer.Receive(ref groupEP);
udpServer.Send(new byte[] { 1 }, 1); // if data is received reply letting the client know that we got his data
}
Edit
the reason why I cannot use tcp is because sometimes the client is behind a NAT (router) and it is simpler to do UDP hole punching than TCP.
Solution:
thanks to markmnl answer here is my code:
Server:
UdpClient udpServer = new UdpClient(11000);
while (true)
{
var remoteEP = new IPEndPoint(IPAddress.Any, 11000);
var data = udpServer.Receive(ref remoteEP); // listen on port 11000
Console.Write("receive data from " + remoteEP.ToString());
udpServer.Send(new byte[] { 1 }, 1, remoteEP); // reply back
}
Client code:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening
client.Connect(ep);
// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);
// then receive data
var receivedData = client.Receive(ref ep);
Console.Write("receive data from " + ep.ToString());
Console.Read();
(I presume you are aware that using UDP(User Datagram Protocol) does not guarantee delivery, checks for duplicates and congestion control and will just answer your question).
In your server this line:
var data = udpServer.Receive(ref groupEP);
re-assigns groupEP from what you had to a the address you receive something on.
This line:
udpServer.Send(new byte[] { 1 }, 1);
Will not work since you have not specified who to send the data to. (It works on your client because you called connect which means send will always be sent to the end point you connected to, of course we don't want that on the server as we could have many clients). I would:
UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);
while (true)
{
var remoteEP = new IPEndPoint(IPAddress.Any, 11000);
var data = udpServer.Receive(ref remoteEP);
udpServer.Send(new byte[] { 1 }, 1, remoteEP); // if data is received reply letting the client know that we got his data
}
Also if you have server and client on the same machine you should have them on different ports.
I'll try to keep this short, I've done this a few months ago for a game I was trying to build, it does a UDP "Client-Server" connection that acts like TCP, you can send (message) (message + object) using this. I've done some testing with it and it works just fine, feel free to modify it if needed.
here is my soln to define the remote and local port and then write out to a file the received data, put this all in a class of your choice with the correct imports
static UdpClient sendClient = new UdpClient();
static int localPort = 49999;
static int remotePort = 49000;
static IPEndPoint localEP = new IPEndPoint(IPAddress.Any, localPort);
static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), remotePort);
static string logPath = System.AppDomain.CurrentDomain.BaseDirectory + "/recvd.txt";
static System.IO.StreamWriter fw = new System.IO.StreamWriter(logPath, true);
private static void initStuff()
{
fw.AutoFlush = true;
sendClient.ExclusiveAddressUse = false;
sendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sendClient.Client.Bind(localEP);
sendClient.BeginReceive(DataReceived, sendClient);
}
private static void DataReceived(IAsyncResult ar)
{
UdpClient c = (UdpClient)ar.AsyncState;
IPEndPoint receivedIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);
fw.WriteLine(DateTime.Now.ToString("HH:mm:ss.ff tt") + " (" + receivedBytes.Length + " bytes)");
c.BeginReceive(DataReceived, ar.AsyncState);
}
static void Main(string[] args)
{
initStuff();
byte[] emptyByte = {};
sendClient.Send(emptyByte, emptyByte.Length, remoteEP);
}
Wireshark captures UDP packets in my LAN with follwoing details
Source IP 192.168.1.2
Destination IP 233.x.x.x
Source Port 24098
Destination Port 12074,12330
how can i capture it in c#?
Solved it myself
Here is my working code
class CAA
{
private Socket UDPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private IPAddress Target_IP;
private int Target_Port;
public static int bPause;
public CAA()
{
Target_IP = IPAddress.Parse("x.x.x.x");
Target_Port = xxx;
try
{
IPEndPoint LocalHostIPEnd = new
IPEndPoint(IPAddress.Any, Target_Port);
UDPSocket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.NoDelay, 1);
UDPSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
UDPSocket.Bind(LocalHostIPEnd);
UDPSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 0);
UDPSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new
MulticastOption(Target_IP));
Console.WriteLine("Starting Recieve");
Recieve();
}
catch (Exception e)
{
Console.WriteLine(e.Message + " " + e.StackTrace);
}
}
private void Recieve()
{
try
{
IPEndPoint LocalIPEndPoint = new
IPEndPoint(IPAddress.Any, Target_Port);
EndPoint LocalEndPoint = (EndPoint)LocalIPEndPoint;
StateObject state = new StateObject();
state.workSocket = UDPSocket;
Console.WriteLine("Begin Recieve");
UDPSocket.BeginReceiveFrom(state.buffer, 0, state.BufferSize, 0, ref LocalEndPoint, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void ReceiveCallback(IAsyncResult ar)
{
IPEndPoint LocalIPEndPoint = new
IPEndPoint(IPAddress.Any, Target_Port);
EndPoint LocalEndPoint = (EndPoint)LocalIPEndPoint;
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceiveFrom(ar, ref LocalEndPoint);
client.BeginReceiveFrom(state.buffer, 0, state.BufferSize, 0, ref LocalEndPoint, new AsyncCallback(ReceiveCallback), state);
}
public static void Main()
{
CAA o = new CAA();
Console.ReadLine();
}
public class StateObject
{
public int BufferSize = 512;
public Socket workSocket;
public byte[] buffer;
public StateObject()
{
buffer = new byte[BufferSize];
}
}
}
The Winpcap library is one of the best ways to do this. I have experience in doing this in C# and it was really easy to work with this library.
This project shows how to do it with C#.
Wireshark actually uses Winpcap to do this, and as the other answer indicates, you can use it as well.
You can also use the System.Net.Sockets.Socket class and place it in promiscuous mode. I use this to capture the IP traffic (e.g., TCP and UDP) from a given network interface. Here's an example.
using System.Net;
using System.Net.Sockets;
Socket socket =
new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Parse("X.X.X.X"), 0)); // specify IP address
socket.ReceiveBufferSize = 2 * 1024 * 1024; // 2 megabytes
socket.ReceiveTimeout = 500; // half a second
byte[] incoming = BitConverter.GetBytes(1);
byte[] outgoing = BitConverter.GetBytes(1);
socket.IOControl(IOControlCode.ReceiveAll, incoming, outgoing);
Now that the socket is created and configured, you can use the Receive() method to start receiving data. Each time you call Receive(), the returned buffer will contain an IP packet. See here for the breakout of the IPv4 header, here for the UDP header, and here for the TCP header. If the Protocol field of the IP header contains a value of 17, then you have a UDP packet.
NOTE Raw sockets on Windows require that you be an administrator on your local system. The following language is contained in this MSDN article.
To use a socket of type SOCK_RAW
requires administrative privileges.
Users running Winsock applications
that use raw sockets must be a member
of the Administrators group on the
local computer, otherwise raw socket
calls will fail with an error code of
WSAEACCES. On Windows Vista and later,
access for raw sockets is enforced at
socket creation. In earlier versions
of Windows, access for raw sockets is
enforced during other socket
operations.
In order to use WinPcap for raw packet capturing in C#, you can try Pcap.Net.
It is a wrapper for WinPcap in C++/CLI and C# for easily capturing (sniffing) and injecting raw packets and it also contains an easy to use packets interpretation framework.
Using Pcap.Net in https://github.com/PcapDotNet
Especific exemple: https://github.com/PcapDotNet/Pcap.Net/wiki/Pcap.Net-Tutorial-Interpreting-the-packets
// Callback function invoked by libpcap for every incoming packet
private static void PacketHandler(Packet packet)
{
// print timestamp and length of the packet
Console.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Length);
IpV4Datagram ip = packet.Ethernet.IpV4;
UdpDatagram udp = ip.Udp;
// print ip addresses and udp ports
Console.WriteLine(ip.Source + ":" + udp.SourcePort+ " -> " + ip.Destination + ":" + udp.DestinationPort);
}
Output:
2009-09-12 11:25:51.117 length:84
10.0.0.8:49003 -> 208.67.222.222:53
2009-09-12 11:25:51.212 length:125
208.67.222.222:53 -> 10.0.0.8:49003
2009-09-12 11:25:54.323 length:80
10.0.0.8:39209 -> 208.67.222.222:53
2009-09-12 11:25:54.426 length:75
10.0.0.8:47869 -> 208.67.222.222:53
2009-09-12 11:25:54.517 length:236
208.67.222.222:53 -> 10.0.0.8:39209
2009-09-12 11:25:54.621 length:91
208.67.222.222:53 -> 10.0.0.8:47869