I am trying to fetch the IP address from the broadcast packets sent by a DSL modem and received on port 137 using UDP protocol. I am able to read the IP address when connectivity is present.
However, in unidentified network state, when my modem is configured for DHCP, and a specific range of IPs are allowed, and setting on my machine is auto-detect:
I get the default Local IP Address of the machine on reading the broadcast messages. That would be starting with 169.
Note: I am restarting the modem in order to receive the broadcast messages.
Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 137);
sock.Bind(iep);
EndPoint ep = (EndPoint)iep;
int iLoopCount=0;
while (iLoopCount <= 10000)
{
Console.WriteLine("Ready to receive…");
byte[] data = new byte[1024];
int recv = sock.ReceiveFrom(data, ref ep);
string stringData = Encoding.Default.GetString(data, 0, recv);
Console.WriteLine("{1}: from: {0}",((IPEndPoint)ep).Address.ToString(),DateTime.Now.ToString());
iLoopCount++;
// Console.WriteLine(sock.RemoteEndPoint.ToString());
}
sock.Close();
Console.Read();
Found the answer to my question at
http://www.codeproject.com/Articles/17031/A-Network-Sniffer-in-C
Related
I'm trying to implement Hole punching using C# but unfortunately I spent hours to figure out why it doesn't work for me. Here is my problem:
I have a third part server that I can manage all external IPs for the peers on, and of course my router is behind a NAT, and I assume all my peers are also behind NATs.
Say if I managed to figure out all slaves (peers), End points (external ips). Where to put the external ip address of my server which runs on my pc (not the third party one), and where to put the peer ip address?
This is my code:
public void HolePunch(String ServerIp, Int32 Port) // if I put my external ip here I get Exception (An address incompatible with the requested protocol was used)
{
IPEndPoint LocalPt = new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], Port);
UdpClient Client = new UdpClient();
Client.ExclusiveAddressUse = false;
Client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
Client.Client.Bind(LocalPt);
IPEndPoint RemotePt = new IPEndPoint(IPAddress.Parse(ServerIp), Port);
// This Part Sends your local endpoint to the server so if the two peers are on the same nat they can bypass it, you can omit this if you wish to just use the remote endpoint.
byte[] IPBuffer = System.Text.Encoding.UTF8.GetBytes(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString());
byte[] LengthBuffer = BitConverter.GetBytes(IPBuffer.Length);
byte[] PortBuffer = BitConverter.GetBytes(Port);
byte[] Buffer = new byte[IPBuffer.Length + LengthBuffer.Length + PortBuffer.Length];
LengthBuffer.CopyTo(Buffer,0);
IPBuffer.CopyTo(Buffer, LengthBuffer.Length);
PortBuffer.CopyTo(Buffer, IPBuffer.Length + LengthBuffer.Length);
Client.BeginSend(Buffer, Buffer.Length, RemotePt, new AsyncCallback(SendCallback), Client);
// Wait to receve something
BeginReceive(Client, Port);
// you may want to use a auto or manual ResetEvent here and have the server send back a confirmation, the server should have now stored your local (you sent it) and remote endpoint.
// you now need to work out who you need to connect to then ask the server for there remote and local end point then need to try to connect to the local first then the remote.
// if the server knows who you need to connect to you could just have it send you the endpoints as the confirmation.
// you may also need to keep this open with a keepalive packet untill it is time to connect to the peer or peers.
// once you have the endpoints of the peer you can close this connection unless you need to keep asking the server for other endpoints
Client.Close();
}
public void ConnectToPeer(String PeerIp, Int32 Port)
{
IPEndPoint LocalPt = new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], Port);
UdpClient Client = new UdpClient();
Client.ExclusiveAddressUse = false;
Client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
Client.Client.Bind(LocalPt);
IPEndPoint RemotePt = new IPEndPoint(IPAddress.Parse(PeerIp), Port);
Client.Connect(RemotePt);
//you may want to keep the peer client connections in a list.
BeginReceive(Client, Port);
}
public void SendCallback(IAsyncResult ar)
{
UdpClient Client = (UdpClient)ar.AsyncState;
Client.EndSend(ar);
}
public void BeginReceive(UdpClient Client, Int32 Port)
{
IPEndPoint ListenPt = new IPEndPoint(IPAddress.Any, Port);
Object[] State = new Object[] { Client, ListenPt };
Client.BeginReceive(new AsyncCallback(ReceiveCallback), State);
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient Client = (UdpClient)((Object[])ar.AsyncState)[0];
IPEndPoint ListenPt = (IPEndPoint)((Object[])ar.AsyncState)[0];
Byte[] receiveBytes = Client.EndReceive(ar, ref ListenPt);
}
EDIT :
the code works will if I give it my local ip and if my clients in my pc .. but if I supply it an external ip it doesn't work ( the exception in the first line comment )
I have some client-server socket code that I want to be able to construct and (re)connect to periodically the same endpoint address: localhost:17999
Here is the server:
// Listen for a connection:
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Loopback, 17999);
Socket listener = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listener.Bind(localEndPoint);
listener.Listen(1);
// Accept the connection and send a message:
Socket handler = listener.Accept();
byte[] bytes = new byte[1024];
bytes = Encoding.ASCII.GetBytes("The Message...");
handler.Send(bytes);
// Clean up
handler.Shutdown(SocketShutdown.Both);
handler.Close();
handler.Dispose();
listener.Shutdown(SocketShutdown.Both);
listener.Close();
listener.Dispose();
And here is the client:
byte[] bytes = new byte[1024];
Socket receiver = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
receiver.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiver.Connect(new IPEndPoint(IPAddress.Loopback, 17999));
int num_bytes_received = receiver.Receive(bytes);
string result = Encoding.ASCII.GetString(bytes, 0, num_bytes_received);
receiver.Shutdown(SocketShutdown.Both);
receiver.Close();
receiver.Dispose();
When I create the client and server for the first time, it works fine. However when I create it again, I get an error:
"A request to send or receive data was disallowed because the socket is
not conne cted and (when sending on a datagram socket using a sendto
call) no address was supplied"
I would like to be able to spin up this mechanism arbitrarily whenever I need to with the following order of events:
Launch the server and wait to accept a connection
Launch the client and connect to the server
Accept the client connection at the server
Send a message to the client
Repeat when necessary
How can I do this?
Thx in Advance!
EDIT: Each time I build the client and server objects it is from a different process.
You have two issues:
1) You're closing the listener. Just leave it open.
2) You're setting ReuseAddress on the wrong socket and way too late. Set it on the listening socket before you call bind (since that's when you use the address).
Setting ReuseAddress on a socket you aren't going to bind doesn't do anything. You can remove that from the client.
I tried what Gene suggested and it seems to work:
// Listen for a connection:
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Loopback, 17999);
using (Socket listener = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listener.Bind(localEndPoint);
listener.Listen(1);
Thread t = new Thread(() =>
{
// Accept the connection and send a message:
using (Socket handler = listener.Accept())
{
byte[] bytes = new byte[1024];
bytes = Encoding.ASCII.GetBytes("The Message...");
handler.Send(bytes);
}
});
t.Start();
t.Join();
}
Thanks, all!
I need to determine the IP of a machine that has sent me a multicast packet, so that I can respond to it via unicast.
I'm using the following csharp (.Net 3.5) code to receive the packets over a multicast connection (code has been edited for brevity, with error checking and irrelevant options removed):
IPEndPoint LocalHostIPEnd = new IPEndPoint(IPAddress.Any, 8623);
Socket UDPSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
UDPSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, 1);
UDPSocket.Bind(LocalHostIPEnd);
//Join the multicast group
UDPSocket.SetSocketOption(
SocketOptionLevel.IP,
SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse("225.2.2.6")));
IPEndPoint LocalIPEndPoint = new IPEndPoint(IPAddress.Any ,Target_Port);
EndPoint LocalEndPoint = (EndPoint)LocalIPEndPoint;
// Create the state object.
StateObject state = new StateObject();
state.buffer.Initialize();
state.workSocket = UDPSocket;
state.id = "state0";
//Set up my callback
UDPSocket.BeginReceiveMessageFrom(
state.buffer,
0,
StateObject.BufferSize,
0,
ref LocalEndPoint,
new AsyncCallback(ReceiveCallback),
state);
And here's the callback, where I'm trying to get the source IP:
private void ReceiveCallback( IAsyncResult ar )
{
IPEndPoint LocalIPEndPoint = new IPEndPoint(IPAddress.Any, Target_Port);
EndPoint LocalEndPoint = (EndPoint)LocalIPEndPoint;
// Read data from the remote device.
// The following code attempts to determine the IP of the sender,
// but instead gets the IP of the multicast group.
SocketFlags sFlags = new SocketFlags();
IPPacketInformation ipInf = new IPPacketInformation();
int bytesRead = client.EndReceiveMessageFrom(ar, ref sFlags,
ref LocalEndPoint, out ipInf);
log.Warn("Got address: " + ipInf.Address.ToString());
}
I know the correct source IP is in the IP header, since I can clearly see it there when I sniff the packet in wireshark. However, instead of printing out the IP of the sending system (192.168.3.4), the above code prints out the IP of the multicast group that I am subscribed to (225.2.2.6). Is there a way to get the source IP instead?
Isn't your answer in the LocalEndPoint variable, which is the EndPoint of the packet's source, i.e., the dude on the other end. Note that I would probably rename this variable something like "remoteEP", and initialize it to something non-specific to avoid confusion.
Code server I have server listen on port 1450:
//Using UDP sockets
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint ourEP = new IPEndPoint(IPAddress.Any, 1450);
//Listen asynchronously on port 1450 for coming messages (Invite, Bye, etc).
clientSocket.Bind(ourEP);
//Receive data from any IP.
EndPoint remoteEP = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
byteData = new byte[1024];
//Receive data asynchornously.
clientSocket.BeginReceiveFrom(byteData,
0, byteData.Length,
SocketFlags.None,
ref remoteEP,
new AsyncCallback(OnReceive),
null);
but code on not open port 1450 and client connect:
otherPartyIP = new IPEndPoint(IPAddress.Parse(txtCallToIP.Text), 1450);
otherPartyEP = (EndPoint)otherPartyIP;
When i run code client and server in lan network it's ok. but run over network i check port 1450 in lan not open. tell me how open port 1450 in code server? thanks
I created an application with server and client tool using sockets etc. When using my code on my computer works. Now I installed the Himachi software and I need to use this software in my application so that when a user connects with me, the application created could be used in this network. Note that this is my first time using sockets. The problem is that they are not connecting to each other and also it gives me this error on changing the ip and port: The requested address is not valid in its context
The send Tool
public Send(string Group, string port, string ttl, string rep, string data)
{
IPAddress ip;
try
{
Console.WriteLine("Send on Group: {0} Port: {1} TTL: {2}", Group,port,ttl);
ip = IPAddress.Parse(Group);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip));
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, int.Parse(ttl));
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(Group),int.Parse(port));
Console.WriteLine("Connecting...");
s.Connect(ipep);
byte[] byData = System.Text.Encoding.ASCII.GetBytes(data);
s.Send(byData, SocketFlags.None);
Console.WriteLine("Closing Connection...");
s.Close();
}
catch(System.Exception e) { Console.Error.WriteLine(e.Message); }
}
The Receive tool
public string RecvData(string Group, string port)
{
string str = "";
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, int.Parse(port));
s.Bind(ipep);
IPAddress ip = IPAddress.Parse(Group);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip,IPAddress.Any));
// Getting the data
byte[] buffer = new byte[1024];
int iRx = s.Receive(buffer);
str = System.Text.Encoding.ASCII.GetString(buffer, 0, buffer.Length);
// Closing a Socket
s.Close();
return str;
}
Thanks
So your problem is that you are trying to use a VPN (hamachi) to connect two apps the server and the client so that the client can receive messages from the server right? I think that the error given "The requested address is not valid in its context" is because you are using a VPN but I don't know how this can be solved sorry. What I think is that maybe you might also need the network id and password but again I'm not sure. Please keep us informed because this is a very interesting question.