I am using USR-TCP232 LAN Modules for an embedded project.
I have a tool to query those modules made by the manufacturer, it works great.
But, I want it in my code in C#. So, I decided to make one for myself. I believe I am so close but I guess a small glitch which gives me hard times and I need somebody to put some shed light on.
I can send a UDP broadcast and I can observe the traffic via "WireShark".
It is quite similar with the original tool. But, I can't receive the answered data sent by the devices on the network in my code.
Console application in C#
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
namespace UDPer
{
class Program
{
static void Main(string[] args)
{
UDPer udp = new UDPer();
udp.Starter();
ConsoleKeyInfo cki;
do
{
if (Console.KeyAvailable)
{
cki = Console.ReadKey(true);
switch (cki.KeyChar)
{
case 's':
udp.Send("0123456789012345678901234567890123456789");
break;
case 'x':
udp.Stop();
return;
}
}
Thread.Sleep(10);
} while (true);
}
}
class UDPer
{
private Socket udpSock;
private byte[] buffer;
public void Starter()
{
//Setup the socket and message buffer
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));
udpSock.EnableBroadcast = true;
buffer = new byte[1024];
udpSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//udpSock.ExclusiveAddressUse = false; // only if you want to send/receive on same machine.
//The socket must not be bound or connected.
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}
public void Stop()
{
try
{
udpSock.Close();
Console.WriteLine("Stopped listening");
}
catch { /* don't care */ }
}
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
//Get the received message.
Socket recvSock = (Socket)iar.AsyncState;
recvSock.EnableBroadcast = true;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = new byte[msgLen];
Array.Copy(buffer, localMsg, msgLen);
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
//Handle the received message
Console.WriteLine("Recieved {0} bytes from {1}:{2}",
msgLen,
((IPEndPoint)clientEP).Address,
((IPEndPoint)clientEP).Port);
//Do other, more interesting, things with the received message.
string message = Encoding.ASCII.GetString(localMsg);
Console.WriteLine("Message: {0} ", message);
}
catch (ObjectDisposedException)
{
//expected termination exception on a closed socket.
}
}
public void Send(string message)
{
UdpClient udp = new UdpClient(1500);
var ipEndPoint = new IPEndPoint(IPAddress.Broadcast, 1500);
byte[] data = Encoding.ASCII.GetBytes(message);
udp.Send(data, data.Length, ipEndPoint);
udp.Close();
}
}
}
Wireshark capture
Note that: This Wireshark capture is exactly the same as the original tool does.
Some definitions:
My PC where C# application resides: 192.168.65.82
LAN Module IP Address: 192.168.65.8
Ports must be 1500 which is all OK.
Send payload for querying LAN Modules;
"0123456789012345678901234567890123456789"
So, I have tried tons of different options one by one but no jo so far.
What am I missing here?
A socket always has a dedicated port. Passing an IPEndPoint with port number 0 doesn't mean that you receive packets send to any port. Instead you are binding to a port assigned by the underlying service provider.
udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));
If you do not care which local port is used, you can create an IPEndPoint using 0 for the port number. In this case, the service provider will assign an available port number between 1024 and 5000
https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.bind(v=vs.110).aspx
You need to use
udpSock.Bind(new IPEndPoint(IPAddress.Any, 1500));
Related
I am working on a small project and I am at the point where I want to connect my Raspberry Pi to Unity (running on my PC). I am able to make a connection running Visual Studio, but when I run the same code in Unity, no connections happen.
C# Code
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener() {
}
public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
//IPAddress ipAddress = Array.Find(ipHostInfo.AddressList, x => x.AddressFamily == AddressFamily.InterNetwork);
IPAddress ipAddress = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 6670);
Console.WriteLine($"Connected on {localEndPoint}");
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp );
// Bind the socket to the local endpoint and listen for incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);
while (true) {
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );
Console.WriteLine("Accepted");
// Wait until a connection is made before continuing.
allDone.WaitOne();
Console.WriteLine("After wait");
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
var stringRead = Encoding.ASCII.GetString(
state.buffer, 0, bytesRead);
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture);
Console.WriteLine(timestamp + ": " + stringRead);
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
//Test Code
Send(handler, "boogieboogie");
}
}
}
private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args) {
Thread t = new Thread(StartListening);
t.Start();
//FingerMovement.Service();
return 0;
}
}
The Python code is just doing a socket connect to the IP and port.
So to restate the question: Why does it not connect to the RPI when I run this in Unity? No connections occur, however, if I run the same exact code through VS, it connects just fine.
I allowed Unity in my firewall, tried running it in Admin, still nothing.
It's a bit of a long shot but have you enabled 'run in the background' checkbox in the player settings? I've had unity miss a whole lot of system events / transmissions while I was switching windows when this was off. I think all the child processes freeze when Unity looses focus by default, and I think that inclueds the async quasi-processes, or at the very least it surely includes your main thread which communicates with you
I have an Android app (really Xamarin app) and I'm using Socket to listen on port 8888 on the Android app.
So, I want to connect to this port from another computer by tcp (from PC TO Android).
And, I receive the following error:
No connection could be made because the target machine actively refused it.
error 10061
My code (I got it from MS examples) works for two console apps. But if Android is server it doesn't work.
I try ping phone from pc, and it is OK.
My question: maybe should open a port? Or something else? How can I do this?
I will gladly to listen any ideas. Thanks.
My server code. C#, Xamarin.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Android.Runtime;
using Java.Lang;
using Byte = System.Byte;
using Exception = System.Exception;
using String = System.String;
using StringBuilder = System.Text.StringBuilder;
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
IPAddress ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 });
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 8888);
// 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(remoteEP);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
My client code. Just simple C# console app:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class SynchronousSocketClient
{
public static void StartClient() {
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
Console.WriteLine("Start!");
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
IPAddress ipAddress = new IPAddress(new byte[] { 10, 0, 1, 173 });
// IPAddress ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 });
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 8888);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try {
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>");
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes,0,bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}",se.ErrorCode);
Console.WriteLine("SocketException : {0}",se.SocketErrorCode);
Console.WriteLine("SocketException : {0}",se.ToString());
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
} catch (Exception e) {
Console.WriteLine( e.ToString());
}
}
}
There are two separate scenarios for socket-based data transport (in a typical local lan setting where there is an ordinary isp router in place):
Any client app (including browser) that connects to a well-known server endpoint (specific ip address and port) and just connects to establish a tcp session, and never listens. This is no problem. The router allows allows outgoing connection attempts.
Any client app that wants to connect to another client app that is listening. This is more difficult in that the router in a local lan setting does not typically allow any incoming connection attempts to a local host. Further the router is probably doing NAT translation so it has an addressable internet-facing ip address and has configured a specific external port to route to a specific internal host machine that is presumably listening at a local address and port.
There are several ways to determine what this endpoint addressing mapping configuration is but none of them are very convenient. The key point is that the router will only open an internal host to communications from the external internet if that host has previously tried to tcp connect to that external host (whether it be a server or a peer client app). This works for the browser/website server configuration because the client is always doing the connecting so the router opens the communication channel for that specific addressed external server and allows incoming data to be received by the client (browser). It is a similar situation for udp data transport. The router will only open the internal host to external incoming udp data if the internal client has recently sent a message to that specific peer. Http (a Tcp variant) provides the client/server protocol that uses this router convention for browser/website connectivity and communications. But for the peer client that wants to act as both a client and a server, there are significant barriers. Of course local lan socket communications are no problem, as local ip addresses are available for any internal lan peer.
I have been searching the internet for a week or two now to find a UDP client program that can send and receive at the same time but there is nothing on this subject for c#. In the last few days I have tried create a UDP client with a thread that receives.
Sending UDP packets works great but the program can not receive for the server i sent to, I believe the server is sending all packets to a different port.
How do i fix this program?
Is there an easier way to do UDP programming like StreamReader and StreamWriter for TCP?
static void CONNECTudp()
{
Console.WriteLine("Host:");
IPAddress ipAddress = Dns.Resolve(Console.ReadLine()).AddressList[0];
Console.WriteLine("Port:");
int Port = int.Parse(Console.ReadLine());
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Port);
Thread UDPthread = new Thread(() => CONNECTudpthread(ipEndPoint));
UDPthread.Start();
UdpClient udp = new UdpClient();
do
{
Byte[] sendBytes = Encoding.ASCII.GetBytes(Console.ReadLine());
udp.Send(sendBytes, sendBytes.Length, ipEndPoint);
} while (true);
}
static void CONNECTudpthread(IPEndPoint ipEndPoint)
{
UdpClient udp = new UdpClient();
do
{
try
{
Byte[] receiveBytes = udp.Receive(ref ipEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
catch (Exception)
{
}
} while (true);
}
Since UDP is message-oriented and not stream-oriented, there's not really a practical way to use StreamReader and StreamWriter with UDP. Sticking with the message-oriented I/O as in your example is best.
The problem in your code is that you are using two different UdpClient instances for sending and receiving. You don't show the UDP server code, so I can't guarantee that's correct either. But if it is, then if you fix your code to be something more like the following, it should work:
static void CONNECTudp()
{
Console.WriteLine("Host:");
IPAddress ipAddress = Dns.Resolve(Console.ReadLine()).AddressList[0];
Console.WriteLine("Port:");
int Port = int.Parse(Console.ReadLine());
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Port);
// Bind port immediately
UdpClient udp = new UdpClient(0);
// Pass UdpClient instance to the thread
Thread UDPthread = new Thread(() => CONNECTudpthread(udp));
UDPthread.Start();
do
{
Byte[] sendBytes = Encoding.ASCII.GetBytes(Console.ReadLine());
udp.Send(sendBytes, sendBytes.Length, ipEndPoint);
} while (true);
}
static void CONNECTudpthread(UdpClient udp)
{
do
{
try
{
// Though it's a "ref", the "remoteEP" argument is really just
// for returning the address of the sender.
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udp.Receive(ref ipEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
catch (Exception)
{
}
} while (true);
}
Iam trying to send a message (via UDP) from my client to my server. The server should answer this message and if the client receives this answer he should print out a message.
If i run the client and server on my local network everything works fine.
If i try to connect through the internet from another PC outside my network the server receives the request of the client, sends an answer back, but the client never receives this answer. The client and the server are both behind a NAT but i portforwarded the ports at the server´s NAT and the server got its own DNS. I already tried NAT traversal but it gives me the same IP and port adress as the IPEndPoint of the server, after receiveing the request of the client, does.
I´ve got no idea how to fix this, so any guidance would be much appreciated.
Client
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
object[] oData = {1};
sendData(oData, 0,0, "Li");
while (true)
{
Console.ReadLine();
}
}
private void receiveData()
{
string receivePort = 8080;
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.ReceiveTimeout = 1000;
IPEndPoint end = new IPEndPoint(IPAddress.Any, receivePort);
client.Bind(end);
while (true)
{
try
{
byte[] data = new byte[1024];
client.Receive(data, 0, data.Length, SocketFlags.None);
object[] receivedObj = Deserialize(data);
string sType = (string)receivedObj[3];
if (sType == "Li")
{
console.WriteLine("received Li");
}
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
public static void sendData(object[] oData, int iFrom, int iTo, string sType)
{
string sendPort = 17171;
UdpClient client = new UdpClient();
string IP = "ThisIsTheDNSofmyServer.com"; //ServerDNS
//string IP = "192.168.xxx.xxx"; //serverIP in LAN
if (IP.StartsWith("T"))
{
IP = (Dns.GetHostAddresses(IP))[0].ToString();
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
oData[1] = iFrom;
oData[2] = iTo;
oData[3] = sType;
Byte[] data = Serialize(oData);
client.Send(data, data.Length, remoteEndPoint);
}
The server´s code is almost the same:
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
while (true)
{
Console.ReadLine();
}
}
private static void ReceiveData()
{
int receivePort = 17171;
UdpClient client = new UdpClient(receivePort);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
data = client.Receive(ref anyIP);
object[] receivedObj = Deserialize(data);
//if I receive data send an Answer
sendData(receivedObj, 0,0,"Li",anyIP.Address.ToString());
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
private static void sendData(object[] oData, int iFrom, int iTo, string sType, string IP)
{
int sendPort = 8080;
object[] paket = { oData, iFrom, iTo, sType };
UdpClient client = new UdpClient();
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
client.Send(data, data.Length, remoteEndPoint);
}
i believe this is a port cofniguration issue,
8080 is almost likely to be configured as alternate http
"The UdpClient you use to receive datagrams must be created using the multicast port number" from MSDN
Hope this helps and good luck
Krishna
You do not need to do anything unordinary to traverse NAT in the setup you described, you just need to send it from the server back to your client; specifically: you must send back to the end point, i.e. IP and port, you received it on.
client.Send(data, data.Length, remoteEndPoint); // remoteEndPoint is the IPEndPoint you got the datagram on
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