UDP networking with multiple network - c#

I'm currently developing a network application on my machine with 2 network interfaces with the following setup -
I want to send UDP message by using the first configuration with IP 192.168.1.2.
using (var udpClient = new UdpClient(5556))
{
udpClient.Connect(IPAddress.Parse("192.168.1.2"), 5556);
// DO STUFF
}
When I try this I get the following error -
No connection could be made because the target machine actively
refused it
Strange this is that when I disable my other network that this works perfectly but with 2 connections (LAN & WiFi) it doesn't work anymore...
I guess that it is sending on wrong adapter?
Is this because my Default gateway is the same or what am I doing wrong?
I'm new to developing network-based applications...

You have to specify an IPEndPoint with networking card IP like this:
var endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.2"), portNum);
UdpClient client = new UdpClient(endpoint);

You are not telling UdpClient which IP to use.
UdpClient has a constructor that can take an IPEndPoint.
const string ip = "192.168.1.2";
const int port = 5556;
var listenEndpoint = new IPEndPoint(IPAddress.Parse(ip), port);
var udpClient = new UdpClient(listenEndpoint);

I'm not that good in C# but I think I understand the problem. You are binding your udpClient to port 5556 but you're not specifying the IP address. The OS will select the IP address for you. I suppose it could be either 192.168.1.2 or 192.168.1.5, you cannot tell which one.
Then with the same udpClient you are trying to connect to a remote host listening on 192.168.1.2, port 5556. And probably nobody is listening there. This is why you receive the error.
I would do the following (sorry for my bad C# skills):
Have two udpClient's, in one thread or program/process:
var udpClient1 = new UdpClient("192.168.1.2", 5556);
This one will listen on IP addres 192.168.1.2, port 5556.
in second thread or program/process:
var udpClient2 = new UdpClient(); //doesn't matter which (IP, port) the OS will bind it to.
udpClient2.Connect(IPAddress.Parse("192.168.1.2"), 5556); //connect to peer/server listening in (IP=192.168.1.2, port=5556)
You could handle both udpClient1 and udpClient2 in the same thread also.
The important is that if you connect to and (IP, port) there has to be some application/process listening there. Otherwise, the remote host will send an ICMP message indicating the datagram cannot be delivered. The connection is refused.

Related

C# - UDP SocketException - Conflict between applications

I'm building a dashboard like website for a formula 1 game.
I followed this guide. (Section : Enabling the UDP Telemetry Output)
Basically, the game sends packets on 127.0.0.1:20777 using UDP, and I'm trying to receive these packets in my app.
My problem is that there seems to be some sort of conflict between the game and my app when I try to receive the packets. For instance, if I compile the app when the game is not running, it compiles just fine, but of course, I do not receive any data.
Once the game is started, I cannot compile, and get a SocketException that says "Only one usage of each socket address (protocol/network address/port) is normally permitted".
I tried the following :
UdpClient client = new UdpClient(20777);
and
UdpClient client = new UdpClient();
IpEndPoint ip = new IpEndPoint(IpAdress.Any, 20777);
client.Connect(ip);
The first solution throws "Only one usage...", and the second solution throws "The requested address is not valid in its context". I am very new to UDP, so I don't really know what am I doing wrong or how to fix it.
Thanks !
i believe you should be trying to listen on the port 20777 rather than trying to connect.
May be something like this:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 20777 ); // endpoint where server is listening
client.Connect(ep);
// then receive data
var receivedData = client.Receive(ref ep);
Console.Write("receive data from " + ep.ToString());
Console.Read();

How to set up TCP communication between two computers

I am trying to use the TCP protocol with the System.Net.Sockets library to have one computer send a string to the other. Here is part of my host code. Is the listener object supposed to be declared with the client IP address or the host IP address (like it is in the code below)?
IPAddress ipAddr = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0]; //Automatically retrieves IPAddress.
int port = 135; //specify port number.
TcpListener listener = new TcpListener(ipAddr, port);
Also, here is a piece of my client code. Which constructor do I use?
TcpClient client = new TcpClient();
The listener object listens on the host's IP. The constructor takes it as an argument because you could have several IP's on the computer and it doesn't know which one you want to listen on.
As far as the client goes, you can pick whichever constructor you want. By using the parameterized constructors, you can connect right away, whereas the default requires a call to one of the overloads of Connect. It mostly depends on if you actually want to connect at instantiation time.
See MSDN for the overloads you can use.
Here is a TCP server sample code:
int port = 135; //specify port number.
TcpListener listener = new TcpListener(IPAddress.Any, port);
// Start listening for client requests
listen.Start();
And then you can select to use polling method to create a simple sync TCP server.
The client (PowerShell):
$Address = [System.Net.Dns]::GetHostAddresses("<hostName>")
$Port = 135
$client = New-Object System.Net.Sorckets.TcpClient
$Client.Connect($Address, $Port)

UDP hole punching. Have server talk to client

I been reading a lot on how to implement UDP hole punching but fore some reason I cannot make it work.
For those that are not familiar of what udp hole punching is here is my own definition:
The goal is to be able to transfer data between two clients (Client A
and client B) with the help of a server. So client A connects to the server and sends its info. Client B does the same. The server has the nessesary info so that Client A is able to send data to Client B and vise versa . Therefore the server gives that info to both clients. Once both clients have that info about each other it is possible to start sending and receiving data between those clients without the help of the server.
My goal is to be able to do what I just described (udp hole punching). Before doing so I think it will be helpful to be able to connect from the server to the client. In order to do so I plan to send the server the info about the client. Once the server receives that info attempt to connect to the client from scratch. Once I am able to perform that I should have everything I need to start implementing the real udp hole punching.
Here is how I have things set up:
The top router has the server and bottom router connected to LAN ports. The bottom router (NAT) is connected to the top router via it's WAN port. And the client computer is connected to the bottom router to one of its LAN ports.
So in that connection the client is able to see the server but the server is not able to see the client.
So the algorithm I have done in pseudo code is:
Client connects to server.
Client send some UDP packages to the server in order to open some ports on the NAT
Send information to the server on what ports the client is listening to.
Once the server receives that info attempt to connect to the client from scratch.
Here is the implementation in code:
Server:
static void Main()
{
/* Part 1 receive data from client */
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
string received_data;
byte[] receive_byte_array = listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
// get info
var ip = groupEP.Address.ToString();
var port = groupEP.Port;
/* Part 2 atempt to connect to client from scratch */
// now atempt to send data to client from scratch once we have the info
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint endPointClient = new IPEndPoint(IPAddress.Parse(ip), port);
sendSocket.SendTo(Encoding.ASCII.GetBytes("Hello"), endPointClient);
}
Client:
static void Main(string[] args)
{
/* Part 1 send info to server */
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse("192.168.0.132");
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, 11000);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
/* Part 2 receive data from server */
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer);
}
For some reason it worked a few times! It works when the client receives data successfully on the line: sending_socket.Receive(buffer);
Things to note:
If on the server on the second part I used the instance variable listner instead of creating the new variable sendSocket and send the bytes through that variable the client is able to receive the data being sent. Remember that the second part of the server is going to be implemented by a second client B that's why I am initializing variables again from scratch...
Edit:
Here is a different way of looking at the same problem. When I initialize a new object instead of using the same object the client does not receives the response.
I have a object of type UdpClient. I am able to send data with that object to the other peer. If I create another object of the same type with the same properties and attempt to send data it does not work! I might be missing to initialize some variables. I am able to set private variables with reflection so I should not have a problem. anyways here is the server code:
public static void Main()
{
// wait for client to send data
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
// connect so that we are able to send data back
listener.Connect(groupEP);
byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };
// now let's atempt to reply back
// this part does not work!
UdpClient newClient = CopyUdpClient(listener, groupEP);
newClient.Send(dataToSend, dataToSend.Length);
// this part works!
listener.Send(dataToSend, dataToSend.Length);
}
static UdpClient CopyUdpClient(UdpClient client, IPEndPoint groupEP)
{
var ip = groupEP.Address.ToString();
var port = groupEP.Port;
var newUdpClient = new UdpClient(ip, port);
return newUdpClient;
}
the client code basically sends data to the server and then waits for a response:
string ipOfServer = "192.168.0.132";
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- keeps waiting in here :(
note that the client is behind a router (NAT) otherwise I will not have this problem. The reason why I will like to copy udpClient is so that I can send that variable to another computer enabling the other computer to send data to the client.
So my question is why is the original object listener able to send data but newClient is not able to? The client keeps waiting at line sending_socket.Receive(buffer); even after the server executes the line: newClient.Send(dataToSend, dataToSend.Length);. the client successfully receives data when listener sends the data but not newClient. Why is this if both variables have the same destination IP and port? how do the variables differ?
Note:
If the server and client are on the same network then the copy works and variable newClient is able to send data to the client. To simulate this problem the client must be behind a NAT (router). An example of such network may consist of two routers. let's call them router X and router Y. You also need a Server call that S. and a client C. so S can be connected to one of the LAN ports of X. C can be connected to one of the LAN ports of Y. Finally connect the WAN port of Y to one of the LAN ports of X.
Hmm, I think you are confusing several things here. For one thing, it's really called UDP hole punching. Let me try to explain how this should work.
NAT routers usually do port mapping when forwarding packets from the inside private network to the outside internet.
Say you created a UDP socket on a machine behind NAT, and sent a datagram to some external IP/port. When the IP packet carrying that datagram leaves the sending machine, its IP header has the source address field set to local not-globally-routable private IP address (like 192.168.1.15), and UDP header has the source port field set to whatever port was assigned to the socket (either explicitly via binding, or implicitly picked by the OS from the ephemeral ports). I'll call this source port number P1.
Then when the NAT router sends that packet out on the outside network, it overwrites the source IP address to its own external IP address (otherwise there's no way to route packets back), and often overwrites the source UDP port to some other value (maybe because some other host on the private network uses the same source port, which creates ambiguity). The mapping between the original source port and that new port number (let's label it P2) is preserved in the router to match return packets. This mapping might also be specific to the target IP address and target UDP port.
So now you have "punched a hole" in the router - UDP packets sent back to the router to port P2 are forwarded to internal machine on UDP port P1. Again, depending on NAT implementation, this could be restricted to only packets from the original target IP address and target UDP port.
For client-to-client communication you'll have to tell external IP/port of one to the other through the server, hoping that the NAT router maps same internal source ports to same external source ports. Then the clients will send packets to each other using those.
Hope this helps.
Finally found the answer! Here is the implemenation with just a client and a server. My next attempt will be to use 3 computers. anyways hope this helps:
Server code:
class Program
{
static byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };
// get the ip and port number where the client will be listening on
static IPEndPoint GetClientInfo()
{
// wait for client to send data
using (UdpClient listener = new UdpClient(11000))
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
return groupEP;
}
}
static void Main(string[] args)
{
var info = GetClientInfo(); // get client info
/* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
*/
// create a new client. this client will be created on a
// different computer when I do readl udp punch holing
UdpClient newClient = ConstructUdpClient(info);
// send data
newClient.Send(dataToSend, dataToSend.Length);
}
// Construct a socket with the info received from the client
static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
{
var ip = clientInfo.Address.ToString();
var port = clientInfo.Port;
// this is the part I was missing!!!!
// the local end point must match. this should be the ip this computer is listening on
// and also the port
UdpClient client = new UdpClient(new IPEndPoint( IPAddress.Any, 11000));
// lastly we are missing to set the end points. (ip and port client is listening on)
// the connect method sets the remote endpoints
client.Connect(ip, port);
return client;
}
}
client code:
string ipOfServer = "192.168.0.139";
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- we can receive data now!!!!!
Have you considered using UPnP on the client to configure NAT traversal to allow incoming packets on a particular port? The client would then only need to communicate the inbound IP and port to the server, and wait for the server to send packets.
http://en.wikipedia.org/wiki/Universal_Plug_and_Play
Seems you are able to connect with the server first time.After successful connection you need to close and disconnect the connection each time.Please check this sample code
http://codeidol.com/csharp/csharp-network/Connectionless-Sockets/A-Simple-UDP-Application/

TcpClient connect fails with IPv6Any

The problem is, the following code works well if IPAddress.Any was given as a parameter, but throws an error if `IPAddress.IPv6Any is used.
I receive error #10057
Socket is not connected.
A request to send or receive data was disallowed because the socket is
not connected and (when sending on a datagram socket using
sendto) no address was supplied. Any other type of operation might
also return this error—for example, setsockopt setting SO_KEEPALIVE if
the connection has been reset.
Why does it fails to work as IPv6Any? I'm pretty sure it's not the firewall, since the port remains the same and it works with IPv4 (and my firewall should pass any requests made by my application).
To short up the code, it's something like this:
The Listener:
listener = new TcpListener(IPAddress.IPv6Any, portNr);
listener.AllowNatTraversal(true);
listener.Start();
listener.BeginAcceptTcpClient(this.AcceptClient, null);
The Client:
client = new TcpClient();
client.NoDelay = true;
try
{
this.client.Connect(ip, port); //ip = "localhost" when connecting as server
}
catch (Exception ex)
{
FileLogger.LogMessage(ex);
Disconnect();
}
I'm trying to set up the "server-side" of the TCP-connection.
What I do is that I start a listener at localhost, and then connect to it as a client (and allow others to join as clients as well).
What I'm trying to achieve with this is direct addressability of this TCP server, following this article: http://blogs.msdn.com/b/ncl/archive/2009/07/27/end-to-end-connectivity-with-nat-traversal-.aspx
The reason I'm doing this is that I want person A to be able to connect to a person B when they both are behind NAT routers.
I know this answer comes a bit late, but I also had this issue and it was client related. The problem is, that your provided code...
client = new TcpClient();
... creates an IPv4-Instance of the TcpClient that is not capable of interpreting IPv6-Addresses. So if you already have the IP address at the moment of initialization, try to initialize your TcpClient like this:
TcpClient client = new TcpClient(ip.AddressFamily);
If the variable ip is a string, you need to convert it to type IPAddress first:
IPAddress iAddr = IPAddress.Parse(ip);
Actually a IPv6-TcpClient seems to be compatible to IPv4-Addresses as well, so you can also initialize your client as follows:
TcpClient client = new TcpClient(AddressFamily.InterNetworkV6)
Whilst the upper suggestions seem to be the cleanest ones, the bottom suggestion seems to be the more universal one. At the end it's up to your preferences.
I solved a similar issue where the following line would only block connections coming from IPv4 addresses:
listener = new TcpListener(IPAddress.IPv6Any, portNr);
It seems the socket when configured to accept IPv6 connections, by default, accepts ONLY IPv6 connections. To fix this problem i had to update my code to this:
listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
listener.Start();
When you use TcpClient.Connect(string, int) you make it possible to break because of DNS resolution.
Though Microsoft documents that IPv6 address will be tried first, the resolution may only return IPv4 addresses.
http://msdn.microsoft.com/en-us/library/8s2yca91.aspx
Therefore, can you try to call TcpClient.Connect(IPAddress.IPv6Loopback, port) on client side to test if it works?
IPAddress.Loopback == FAIL
IPAddress.IPv6Loopback == SUCCESS
Perhaps localhost is mapping to the IPv4 Loopback Address in your case?

C# UDP broadcast client/server does not work

I'm using .NET 2.0 and have created a fairly simple udp broadcast app and UDP listener.
Listener code:
Socket listener = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
IPEndPoint localEndPoint = new IPEndPoint( IPAddress.Any, 11000 );
listener.Bind( localEndPoint );
EndPoint ep = (EndPoint)localEndPoint;
Console.WriteLine("Ready to receive…");
byte[] data = new byte[1024];
int recv = listener.ReceiveFrom(data, ref ep);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine("received: {0} from: {1}", stringData, ep.ToString());
listener.Close();
Server code:
int groupPort = 11000;
IPEndPoint groupEP = new IPEndPoint( IPAddress.Parse( "255.255.255.255" ), groupPort );
if ( radioButton2.Checked )
{
groupEP = new IPEndPoint( IPAddress.Broadcast, groupPort );
}
else if ( radioButton3.Checked )
{
groupEP = new IPEndPoint( IPAddress.Parse( "172.16.75.15" ), groupPort );
}
Socket socket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
socket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1 );
socket.SendTo( System.Text.ASCIIEncoding.ASCII.GetBytes( testTextBox.Text ), groupEP );
The server is just a simple windows app with 3 radio buttons, button and a textbox.
When I run the server on a separate computer and choose radioButton3 I receive the message just fine on my client listener (which is running on ip address 172.16.75.15). However if I choose the first or second radiobutton (which creates Broadcast or 255.255.255.255 as the ip address) I get nothing. Now if I run the client on the same pc as the server I can receive the message using those two choices.
I'm not sure what I'm doing wrong or if there could be some kind of firewall preventing UDP messages on the LAN. Any ideas?
Thanks,
Craig
Try a broadcast on the local subnet only. IE if your subnet is 255.255.255.0 try a broadcast of 172.16.75.255. It may be that windows, a router or even network card automatically block universal broadcasts as a preventative measure.
Is the client on the same physical network as the server? If not, you won't be able to do a local broadcast (255.255.255.255) and will need to do a directed subnet broadcast. You will have to enable your router to allow a directed subnet broadcast (172.16.75.255) before that will work.
I had the similar problem, nothing seemed to work in all the code I saw here.
when I started my program there was this firewall window that pops up telling you the firewall has blocked some features.
my problem was I was clicking allow access without ticking the check box that says "Private networks, suck as my home or work network". you can change this later of course in your firewall setting and tick that check box. both de server and the other machine must have that check box checked. Or at least that's what makes my mine work.
Also i had to change my broadcast IP address to for example 192.168.1.255. My router does block the recommended by my book 224.0.0.0 - 239.255.255.255;
Just a note, but if you are writing a new app from the ground up then you should really be using multicast instead of broadcast.
I just tried your code and worked for me. The only thing i changed was the IPAddress to match my local IP Address for the server.
Craig, I develop a C# udp client/server tool, using broadcasts, it works ( datagrams are received by all the clients on the same subnet ). Just avoid 255.255.255.255, windows cannot always take the right route. You have to help windows specifying the right subnet. Server : bind the udp socket to 172.16.75.15, and sendto the local broadcast address ( are you sure about 172.16.75.255 ? check your subnet mask ).
In my case 255.255.255.255 not working because of Teamviewer VPN driver ,In Network Connections. I am using Subnet mask because of i have to find the device rather than static ip, because ip is often changed for DHCP.

Categories

Resources