How to properly change a static IP address using the Microframework? - c#

I have my Netduino Plus 2 go out to a web service to look up some values that I would like it to use in my project. One of the values that I have the Netduino check is its preferred IP address. If the Netduino has a different IPAddress than its preferred, I want to change it.
I have a method in my project called BindIPAddress (below) that takes a string.
I am getting a SocketException with a code of 10022 for invalid argument. This happens when I call this.Socket.Bind. My class has a property called Socket to hold the Socket value. Is it because my socket already has an endpoint ? I tried adding this.Socket = null and then this.Socket = new (....... thinking we need a new socket to work with, but this returned the same error.
Please advise how I can change my IP address from one static IP address to another.
public void BindIPAddress(string strIPAddress)
{
try
{
Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP(strIPAddress, "255.255.240.0", "10.0.0.1");
Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(new string[] { "10.0.0.2", "10.0.0.3" });
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(strIPAddress), 80);
this.Socket.Bind(ep);
this.IpAddress = strIPAddress;
}
catch(SocketException exc)
{
Debug.Print(exc.Message);
Debug.Print(exc.ErrorCode.ToString());
}
catch(Exception ex)
{
Debug.Print(ex.Message);
}
//Debug.Print(ep.Address.ToString());
}

There may be 2 possible solutions to this problem. The first one is, you can programatically set the preffered IP addresses as the way you have tried to do so and the second one is, you can use MFDeploy tool, which comes with .NET Micro Framework SDK bundle that allows you to set your embedded device network configuration statically before running your application on it.
1) Since you have not provided rest of the code, here's a proper way to bind your socket to an EndPoint (actually, I would not design that class and binding function as the way you posted here, but just wanted to underline the missing parts of your code):
public void BindIPAddress(string strIPAddr)
{
Socket sock = null;
IPEndPoint ipe = null;
NetworkInterface[] ni = null;
try
{
ipe = new IPEndPoint(IPAddress.Parse(strIPAddr), 80);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Assuming the WebService is connection oriented (TCP)
// sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // if it broadcasts UDP packets, use this line (UDP)
ni = NetworkInterface.GetAllNetworkInterfaces();
if (ni != null && ni.Length > 0)
{
ni[0].EnableStaticIP(strIPAddr, "255.255.240.0", "10.0.0.1");
ni[0].EnableStaticDns(new string[2] { "10.0.0.2", "10.0.0.3" });
sock.Bind(ipe);
this.Socket = sock;
this.IpAddress = strIPAddr;
}
else
throw new Exception("Network interface could not be retrieved successfully!");
}
catch(Exception ex)
{
Debug.Print(ex.Message);
}
}
2) Or without programming, just by using MFDeploy tool you can set the preferred IP addresses after plugging your embedded device into your PC and following the path below:
MFDeploy > Target > Configuration > Network
then enter the preferred IP addresses. That's simply all.

Related

WCF web service discovery on network interfaces with multiple IP addresses

I'm trying to do a webservice discovery using WCF's DiscoveryClient using this code:
// Setup the discovery client (WSDiscovery April 2005)
DiscoveryEndpoint discoveryEndpoint = new UdpDiscoveryEndpoint(DiscoveryVersion.WSDiscoveryApril2005);
DiscoveryClient discoveryClient = new DiscoveryClient(discoveryEndpoint);
// Setup the wanted device criteria
FindCriteria criteria = new FindCriteria();
criteria.ScopeMatchBy = new Uri("http://schemas.xmlsoap.org/ws/2005/04/discovery/rfc3986");
criteria.Scopes.Add(new Uri("onvif://www.onvif.org/"));
// Go find!
criteria.Duration = TimeSpan.FromMilliseconds(duration);
discoveryClient.FindAsync(criteria, this);
This works very well on a machine with a single IP address (10.1.4.25) assigned to the single network interface. The broadcast is sent from 10.1.4.25 to 239.255.255.250, and I get responses from 5 devices all on the same subnet.
However, when the machine has multiple IPs on the same interface, it seems to pick a single source IP and sends the request from that.
In this case, I get a reply from a single device giving a 169.254 address.
I have tried setting UdpDiscoveryEndpoint.TransportSettings.MulticastInterfaceId to a suitable interface ID which hasn't helped as it identifies a single interface, not a specific IP.
The UdpDiscoveryEndpoint.ListenUri property also returns the multicast address, and so won't effect the source IP.
UdpDiscoveryEndpoint.Address is the URN for the discovery protocol.
Is there any way I can force it to send from a specific IP address, or ideally, multiple requests on each configured IP?
I have also tried ONVIF Device Manager that seems to have the same problem.
Note that this is not about making a service bind to a specific, or "all address" IP. It is about the IP a discovery request is sent from.
Well, I had the same problem and after some days of research, reading ONVIF documents and learning some tips about multicasting, I developed this code which works fine.
As an example the main IP address on my network adapter is 192.168.80.55 and I also set another IP(192.168.0.10) in advanced settings. With use of this code I can discover device service of a camera with the IP address of 192.168.0.12.
The most important part of this sample is "DeepDiscovery" method which contains the main idea of iteration on network addresses and multicasting proper Probe message.
I recommend deserialization of the response in "GetSocketResponse" method. Currently, just I extract the service URI using Regex.
As mentioned in this article (https://msdn.microsoft.com/en-us/library/dd456791(v=vs.110).aspx):
For WCF Discovery to work correctly, all NICs (Network Interface
Controller) should only have 1 IP address.
I am doing the exact action that WS-Discovery does and using the standard 3702 port, but I myself build the SOAP envelope
and use Socket class for sending the packet for all IP addresses that have been set for the network interface controller.
class Program
{
static readonly List<string> addressList = new List<string>();
static readonly IPAddress multicastAddress = IPAddress.Parse("239.255.255.250");
const int multicastPort = 3702;
const int unicastPort = 0;
static void Main(string[] args)
{
DeepDiscovery();
Console.ReadKey();
}
public static void DeepDiscovery()
{
string probeMessageTemplate = #"<s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-envelope"" xmlns:a=""http://schemas.xmlsoap.org/ws/2004/08/addressing""><s:Header><a:Action s:mustUnderstand=""1"">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action><a:MessageID>urn:uuid:{messageId}</a:MessageID><a:ReplyTo><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand=""1"">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To></s:Header><s:Body><Probe xmlns=""http://schemas.xmlsoap.org/ws/2005/04/discovery""><d:Types xmlns:d=""http://schemas.xmlsoap.org/ws/2005/04/discovery"" xmlns:dp0=""http://www.onvif.org/ver10/device/wsdl"">dp0:Device</d:Types></Probe></s:Body></s:Envelope>";
foreach (IPAddress localIp in
Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(localIp, unicastPort));
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, localIp));
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.MulticastLoopback = true;
var thread = new Thread(() => GetSocketResponse(socket));
var probeMessage = probeMessageTemplate.Replace("{messageId}", Guid.NewGuid().ToString());
var message = Encoding.UTF8.GetBytes(probeMessage);
socket.SendTo(message, 0, message.Length, SocketFlags.None, new IPEndPoint(multicastAddress, multicastPort));
thread.Start();
}
}
public static void GetSocketResponse(Socket socket)
{
try
{
while (true)
{
var response = new byte[3000];
EndPoint ep = socket.LocalEndPoint;
socket.ReceiveFrom(response, ref ep);
var str = Encoding.UTF8.GetString(response);
var matches = Regex.Matches(str, #"http://\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/onvif/device_service");
foreach (var match in matches)
{
var value = match.ToString();
if (!addressList.Contains(value))
{
Console.WriteLine(value);
addressList.Add(value);
}
}
//...
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
//...
}
}
}

C# IPv4/IPv6 agnostic socket listener

I'm trying to to figure out how to create a protocol agnostic socket listener in C# - it should grab IPv4 and IPv6 requests. Everything I can find on Google seems to be C. Attempting something similar to what I saw for C, I tried the following code:
/*Socket*/ m_sock = null;
/*IPAddress*/ m_addr = null;
/*int*/ m_port = port; /*port passed to function*/
/*int*/ m_listenqueue = listen_queue_size; /*also passed to function, number of pending requests to allow before busy*/
IPAddress[] addrs = Dns.GetHostEntry("localhost").AddressList;
if(family == null) m_addr = addrs[0];
else
{
foreach(IPAddress ia in addrs)
{
if(ia.AddressFamily == family) /*desired address family also passed as an argument*/
{
m_addr = ia;
break;
}
}
}
if(m_addr == null) throw new Exception(this.GetType().ToString() + ".#CONSTRUCTOR#: Listener Initailization Error, couldn't get a host entry for 'localhost' with an address family of " + family.ToString());
m_sock = new Socket(m_addr.AddressFamily, SocketType.Stream, ProtocolType.IP);
/*START "AGNOSTICATION LOGIC"... Tried here...*/
if(m_addr.AddressFamily == AddressFamily.InterNetworkV6) //allow IP4 compatibility
{
m_sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.AcceptConnection, true);
/*fails*/ m_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true);
/*fails*/ m_sock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AcceptConnection, true);
}
/*END "AGNOSTICATION LOGIC" */
IPEndPoint _endpoint = new IPEndPoint(m_addr, m_port);
m_sock.Bind(_endpoint);
/*... tried here*/
m_sock.Listen(m_listenqueue);
/*... and tried here*/
I've tried the logic at the three places marked, and regardless of where I put it, the two listed lines will throw an invalid argument exception.
Can anyone recommend to me how I should make a socket that will listen to both IPv4/IPv6?
You can use sock.SetSockOption(SocketOptionLevel.IPv6, SocketOptionName.IPV6Only, 0); to set the socket to allow connections with other protocols than IPv6. It will work from Vista onwards.
SocketOptionName documentation

Weird C# SocketException

While testing my Client-Server program, I encountered a weird exception when trying to connect to the server on a different router:
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond."
The client can connect to the server perfectly in the local network, however it doesn't work when it is over the internet.
I port forwarded port 1250 (the one I'm using), and using SimplePortForwarding (http://www.simpleportforwarding.com/) I verified that the port was open and working.
I based my implementation on this tutorial:
http://www.developerfusion.com/article/3918/socket-programming-in-c-part-1/
Any idea what is wrong?
Thanks!
Here is the server listen method:
public void startListening(int port)
{
lock(_locker)
{
_listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
// Bind socket to local endpoint, and listen for incoming connections
IPEndPoint ipEndpoint = new IPEndPoint(IPAddress.Any, port);
_listeningSocket.Bind(ipEndpoint);
_listeningSocket.Listen(10);
waitForNewClient();
// successfully started listening
_isListening = true;
} catch (SocketException e)
{
// failed for some strange reason
_isListening = false;
}
}
}
Here is the client connect code:
public String connect(String ipAddress, int port)
{
lock(_locker)
{
if (!_connecting)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
_socket.Connect(endpoint);
_connected = true;
waitForData();
_eventManager.queueEvent(new PlayerJoinedEvent(PlayerJoinedEvent.PLAYER_JOINED, name));
} catch (SocketException e)
{
// Exception is thrown HERE
return e.Message;
}
}
}
return "";
}
Make it sure that your Server IP address is public unless it is not reachable.
Check this link for private address spaces.
You opened port 1250 on the server or the client router? It needs to be opened on the server router. You may need to make sure your server is connected to your DMZ port and/or have DMZ enabled on your server router.
Hope this helps.
I Fixed the problem.
The IP Address I used was the internal ip address I got from ipconfig, but the IP address I needed to use was the external one, the one you get from services like http://www.whatsmyip.org/.
I'm still confused as to why these two numbers are different.

Available TCP Port Probe with C#

How can I probe an available TCP Port in order to programmatically configure WCF Service EndPoint ?
How your client will know about the endpoint, if you dynamically choose your server port?
Anyway,
Here is a dirty way of probing for an open port
for (int port = 2000; port < 65535; port++)
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, port);
Socket socket = new Socket(AddressFamily.InterNetwork, st, pt);
try {
socket.Bind(ep);
socket.Close();
//Port available
}
catch (SocketException)
{
Debug.WriteLine("Port not available {0}", port);
}
}
And then, try creating custom service host..
http://msdn.microsoft.com/en-us/library/aa395224.aspx
Not a particularly elegant way, but you can just try opening the host and catch AddressAlreadyInUseException exceptions. That eliminates the use of Socket and the race condition that is present in amazedsaint's method: nothing can occupy the port between the check and your attempt to open the service.
So, basically:
ServiceHost host;
for(int port = 2000; port < 65535; port++) {
var address = GetBaseAddress(port);
host = new ServiceHost(typeof(MyService), address);
try {
host.Open();
break;
}
catch(AddressAlreadyInUseException) {
}
}
The GetBaseAddress method just creates an address with String.Format to put the port number in the right place in your address pattern.
I suppose it's more relevant now seeing as we have WCF Discovery in .NET 4.
What you are looking for is: Socket.Select

In C#, how to check if a TCP port is available?

In C# to use a TcpClient or generally to connect to a socket how can I first check if a certain port is free on my machine?
more info:
This is the code I use:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
Since you're using a TcpClient, that means you're checking open TCP ports. There are lots of good objects available in the System.Net.NetworkInformation namespace.
Use the IPGlobalProperties object to get to an array of TcpConnectionInformation objects, which you can then interrogate about endpoint IP and port.
int port = 456; //<--- This is your value
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
{
if (tcpi.LocalEndPoint.Port==port)
{
isAvailable = false;
break;
}
}
// At this point, if isAvailable is true, we can proceed accordingly.
You're on the wrong end of the Intertube. It is the server that can have only one particular port open. Some code:
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
try {
TcpListener tcpListener = new TcpListener(ipAddress, 666);
tcpListener.Start();
}
catch (SocketException ex) {
MessageBox.Show(ex.Message, "kaboom");
}
Fails with:
Only one usage of each socket address (protocol/network address/port) is normally permitted.
When you set up a TCP connection, the 4-tuple (source-ip, source-port, dest-ip, dest-port) has to be unique - this is to ensure packets are delivered to the right place.
There is a further restriction on the server side that only one server program can bind to an incoming port number (assuming one IP address; multi-NIC servers have other powers but we don't need to discuss them here).
So, at the server end, you:
create a socket.
bind that socket to a port.
listen on that port.
accept connections on that port.
and there can be multiple connections coming in (one per client).
On the client end, it's usually a little simpler:
create a socket.
open the connection.
When a client opens the connection, it specifies the ip address and port of the server. It can specify its source port but usually uses zero which results in the system assigning it a free port automatically.
There is no requirement that the destination IP/port be unique since that would result in only one person at a time being able to use Google, and that would pretty well destroy their business model.
This means you can even do such wondrous things as multi-session FTP since you set up multiple sessions where the only difference is your source port, allowing you to download chunks in parallel. Torrents are a little different in that the destination of each session is usually different.
And, after all that waffling (sorry), the answer to your specific question is that you don't need to specify a free port. If you're connecting to a server with a call that doesn't specify your source port, it'll almost certainly be using zero under the covers and the system will give you an unused one.
Thanks for this tip. I needed the same functionality but on the Server side to check if a Port was in use so I modified it to this code.
private bool CheckAvailableServerPort(int port) {
LOG.InfoFormat("Checking Port {0}", port);
bool isAvailable = true;
// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
foreach (IPEndPoint endpoint in tcpConnInfoArray) {
if (endpoint.Port == port) {
isAvailable = false;
break;
}
}
LOG.InfoFormat("Port {0} available = {1}", port, isAvailable);
return isAvailable;
}
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...how can I first check if a certain port is free on my machine?
I mean that it is not in use by any other application.
If an application is using a port others can't use it until it becomes free. – Ali
You have misunderstood what's happening here.
TcpClient(...) parameters are of server ip and server port you wish to connect to.
The TcpClient selects a transient local port from the available pool to communicate to the server. There's no need to check for the availability of the local port as it is automatically handled by the winsock layer.
In case you can't connect to the server using the above code fragment, the problem could be one or more of several. (i.e. server ip and/or port is wrong, remote server not available, etc..)
thanks for the #jro answer. I had to tweak it for my usage. I needed to check if a port was being listened on, and not neccessarily active. For this I replaced
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
with
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
I iterated the array of endpoints checking that my port value was not found.
To answer the exact question of finding a free port (which is what I needed in my unit tests) in dotnet core 3.1 I came up this
public static int GetAvailablePort(IPAddress ip) {
TcpListener l = new TcpListener(ip, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
Log.Info($"Available port found: {port}");
return port;
}
note: based the comment by #user207421 about port zero I searched and found this and slightly modified it.
string hostname = "localhost";
int portno = 9081;
IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0];
try
{
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) // Port is in use and connection is successful
MessageBox.Show("Port is Closed");
sock.Close();
}
catch (System.Net.Sockets.SocketException ex)
{
if (ex.ErrorCode == 10061) // Port is unused and could not establish connection
MessageBox.Show("Port is Open!");
else
MessageBox.Show(ex.Message);
}
From the available ports I would exclude:
active TCP connections
active TCP listeners
active UDP listeners
With the following import:
using System.Net.NetworkInformation;
You can use the following function to check if a port is available or not:
private bool isPortAvailable(int myPort)
{
var availablePorts = new List<int>();
var properties = IPGlobalProperties.GetIPGlobalProperties();
// Active connections
var connections = properties.GetActiveTcpConnections();
availablePorts.AddRange(connections);
// Active tcp listners
var endPointsTcp = properties.GetActiveTcpListeners();
availablePorts.AddRange(endPointsTcp);
// Active udp listeners
var endPointsUdp = properties.GetActiveUdpListeners();
availablePorts.AddRange(endPointsUdp);
foreach (int p in availablePorts){
if (p == myPort) return false;
}
return true;
}
I give you a similar function for those who use VB.NET:
Imports System.Net.NetworkInformation
Private Function isPortAvailable(ByVal myPort As Integer) As Boolean
Dim props As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()
' ignore active connections
Dim tcpConnInfoArray() As TcpConnectionInformation = props.GetActiveTcpConnections()
For Each tcpi As Net.NetworkInformation.TcpConnectionInformation In tcpConnInfoArray
If tcpi.LocalEndPoint.Port = myPort Then
Return False
End If
Next tcpi
' ignore active TCP listeners
Dim activeTcpListeners() As Net.IPEndPoint = props.GetActiveTcpListeners
For Each tcpListener As Net.IPEndPoint In activeTcpListeners
If tcpListener.Port = myPort Then
Return False
End If
Next tcpListener
' ignore active UPD listeners
Dim activeUdpListeners() As Net.IPEndPoint = props.GetActiveUdpListeners
For Each udpListener As Net.IPEndPoint In activeUdpListeners
If udpListener.Port = myPort Then
Return False
End If
Next udpListener
Return True
End Function
netstat! That's a network command line utility which ships with windows. It shows all current established connections and all ports currently being listened to. You can use this program to check, but if you want to do this from code look into the System.Net.NetworkInformation namespace? It's a new namespace as of 2.0. There's some goodies there. But eventually if you wanna get the same kind of information that's available through the command netstat you'll need to result to P/Invoke...
Update: System.Net.NetworkInformation
That namespace contains a bunch of classes you can use for figuring out things about the network.
I wasn't able to find that old pice of code but I think you can write something similar yourself. A good start is to check out the IP Helper API. Google MSDN for the GetTcpTable WINAPI function and use P/Invoke to enumerate until you have the information you need.
If I'm not very much mistaken, you can use System.Network.whatever to check.
However, this will always incur a race condition.
The canonical way of checking is try to listen on that port. If you get an error that port wasn't open.
I think this is part of why bind() and listen() are two separate system calls.
ipGlobalProperties.GetActiveTcpConnections() doesn't return connections in Listen State.
Port can be used for listening, but with no one connected to it the method described above will not work.
You say
I mean that it is not in use by any
other application. If an application
is using a port others can't use it
until it becomes free.
But you can always connect to a port while others are using it if something's listening there. Otherwise, http port 80 would be a mess.
If your
c = new TcpClient(ip, port);
fails, then nothing's listening there. Otherwise, it will connect, even if some other machine/application has a socket open to that ip and port.
Be aware the time window between you make check and the moment you try to make connection some process may take the port - classical TOCTOU. Why don't you just try to connect? If it fails then you know the port is not available.
You don't have to know what ports are open on your local machine to connect to some remote TCP service (unless you want to use a specific local port, but usually that is not the case).
Every TCP/IP connection is identified by 4 values: remote IP, remote port number, local IP, local port number, but you only need to know remote IP and remote port number to establish a connection.
When you create tcp connection using
TcpClient c;
c = new TcpClient(remote_ip, remote_port);
Your system will automatically assign one of many free local port numbers to your connection. You don't need to do anything.
You might also want to check if a remote port is open. but there is no better way to do that than just trying to connect to it.
public static bool TestOpenPort(int Port)
{
var tcpListener = default(TcpListener);
try
{
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
tcpListener = new TcpListener(ipAddress, Port);
tcpListener.Start();
return true;
}
catch (SocketException)
{
}
finally
{
if (tcpListener != null)
tcpListener.Stop();
}
return false;
}
Check for error code 10048
try
{
TcpListener tcpListener = new TcpListener(ipAddress, portNumber);
tcpListener.Start();
}
catch(SocketException ex)
{
if(ex.ErrorCode == 10048)
{
MessageBox.Show("Port " + portNumber + " is currently in use.");
}
return;
}
I simply needed to verify if a port was available for listening. Condensing #Melloware example above to a one-liner as static method strictly for the purpose of indicating if the port is available works for me (.NET6).
using System.Net.NetworkInformation;
namespace MyNamespace
{
public static class NetworkValidation
{
public static bool IsListeningPortAvailable(int port) =>
!IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Any(x => x.Port == port);
}
}
Implementation as simple console app:
using MyNamespace;
int port = 5000;
var available = NetworkValidation.IsListeningPortAvailable(port);
Console.WriteLine($"Port:{port} available == {available}");
test_connection("ip", port);
public void test_connection(String hostname, int portno) {
IPAddress ipa = (IPAddress)Dns.GetHostAddresses(hostname)[0];
try {
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(ipa, portno);
if (sock.Connected == true) {
MessageBox.Show("Port is in use");
}
sock.Close();
}
catch (System.Net.Sockets.SocketException ex) {
if (ex.ErrorCode == 10060) {
MessageBox.Show("No connection.");
}
}
}
try this, in my case the port number for the created object wasn't available so I came up with this
IPEndPoint endPoint;
int port = 1;
while (true)
{
try
{
endPoint = new IPEndPoint(IPAddress.Any, port);
break;
}
catch (SocketException)
{
port++;
}
}

Categories

Resources