Available TCP Port Probe with C# - 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

Related

c # punch NAT network with TCP / IP protocol

Punching the UDP network works and works. However, when it comes to TCP, it's possible that I'm writing something wrong but I'm not a beginner programmer, or maybe I don't understand something.
Of course, I'll shorten a bit, we assume that we already have something as trivial as connection to an external server :)
Packet synchronization between threads as well as their creation, queuing, serialization, sending raw bytes and much more I skip because it is about the element of creating TCP sockets and not what works.
We will use the TcpListener class for the server.
public void InitializeServer(IPAddress address, int port)
{
try
{
// 127.0.0.1 accept only local connections, 0.0.0.0 is open for whole internet connections
listener = new TcpListener(address, port);
socket = listener.Server;
// Enable NAT Translation
listener.AllowNatTraversal(true);
// Start listening for example 10 client requests.
listener.Start(listenQueue);
Debug.Log($"[L{socket.LocalEndPoint}]Server start... ", EDebugLvl.Log);
OnServerInitialize(true);
// Enter the listening loop.
StartListener();
}
catch (SocketException e)
{
Debug.LogError($"SocketException: {e}", EDebugLvl.Error);
OnServerInitialize(false);
}
}
We start listening
private void StartListener()
{
Debug.Log("\nWaiting for a connection... ");
listener.BeginAcceptTcpClient(AcceptCallback, listener);
}
When the server receives the connection, we create a new socket
private void AcceptCallback(IAsyncResult ar)
{
TcpListener server = (TcpListener)ar.AsyncState;
TcpClient newClient = null;
try
{
newClient = server.EndAcceptTcpClient(ar);
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
if (newClient != null && newClient.Connected)
{
//...
client.StartRead();
}
//Loop
StartListener();
}
We create a new socket at the client and try to establish a connection
public void Connect(IPEndPoint remote, IPEndPoint bind = null, bool reuseAddress = false)
{
if (bind == null)
{
client = new TcpClient();
}
else
{
client = new TcpClient(bind);
}
socket = client.Client;
if (reuseAddress)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
//It throws me a error SocketOption so im comment this.
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, reuseAddress);
}
client.BeginConnect(remote.Address, remote.Port, ConnectCallback, null);
}
The connection works without any problems and data transfer.
Unfortunately, here as we know, we must start a new socket listening on the same address and port that was created when connecting to the server. I do this for every client.
public void StartHost(Client server)
{
if (server != null && server.socket.Connected)
{
IPEndPoint localHost = (IPEndPoint)server.socket.LocalEndPoint;
InitializeHost(localHost.Address, localHost.Port);
}
}
public void InitializeHost(IPAddress address, int port, bool reuse = false)
{
try
{
listener = new TcpListener(address, port);
socket = listener.Server;
if (reuse)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
}
// Enable NAT Translation
listener.AllowNatTraversal(true);
// Start listening for example 10 client requests.
listener.Start(listenQueue);
Debug.Log($"\n[L{socket.LocalEndPoint}]Host start... ", EDebugLvl.Log);
OnServerInitialize(true);
// Enter the listening loop.
StartListener();
}
catch (SocketException e)
{
Debug.LogError($"SocketException: {e}", EDebugLvl.Error);
OnServerInitialize(false);
}
}
private void StartListener()
{
Debug.Log("\nWaiting for a connection... ");
listener.BeginAcceptTcpClient(AcceptCallback, listener);
}
private void AcceptCallback(IAsyncResult ar)
{
TcpListener server = (TcpListener)ar.AsyncState;
TcpClient newClient = null;
try
{
newClient = server.EndAcceptTcpClient(ar);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
if (newClient != null && newClient.Connected)
{
//...
client.StartRead();
}
//Loop
StartListener();
}
So, as they write everywhere ... client "B" sends a packet to the server that wants to establish a connection, the server sends information to the client "A" about the client "B" and vice versa
Then they both try to connect with the new socket? No problem...
public void Connect(IPEndPoint remote, IPEndPoint bind = null, bool reuseAddress = false)
{
if (bind == null)
{
client = new TcpClient();
}
else
{
client = new TcpClient(bind);
}
socket = client.Client;
if (reuseAddress)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, reuseAddress);
}
client.BeginConnect(remote.Address, remote.Port, ConnectCallback, null);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
client.EndConnect(ar);
}
catch (Exception e)
{
Debug.LogError(e.ToString(), EDebugLvl.ConnectionError);
}
if (client.Connected)
{
Debug.Log($"[P{socket.RemoteEndPoint}, L{socket.LocalEndPoint}]Connected", EDebugLvl.ConnectionLog);
stream = new NetworkStream(socket, FileAccess.ReadWrite, true);
StartRead();
}
ConnectedComplete(this, socket.Connected);
}
No matter how many times I try, the connection is rejected ... the addresses match everywhere and yet it does not work, so I have nothing to write about in this case, especially since UDP works for me.
What I wrote only works on the same NAT network. Unfortunately, I noticed that on the same NAT created two connections. One is the result of trying to connect the new socket A to B and the other is the result of receiving a new connection from B to A, so each client has one unnecessary socket connected by a local address. So all NAT TCP / IP Punch NAT doesn't work for me. I can actually use UDP but I really need TCP. I have been sitting on it for several months in my free time but nowhere can I find an example from the code and not the theory of which there is a lot.
I accumulated a lot of knowledge for 8 years and from 2 I write applications using sockets and finally I need to punch the net.
Why won't I use the ready solution? I need my own which is fully open using only UDP and TCP because some target devices only support these protocols. I also used the Socket class but this one did not give me a working copy.
Maybe someone will be able to help me for which I would be very grateful and certainly the post will also help others understand this.
Regards
Octavian
NAT hole punching only works with UDP, and even that is a hack.
NAT firewall implementations will start tracking a TCP stream when they see the initial SYN packet leaving the network. To capture incoming TCP streams you need to create an incoming rule on the router, there's no way around this. If the router supports UPnP, you can ask it to create that rule for you dynamically.
Since UDP doesn't have a SYN packet equivalent, routers will start tracking the stream on any outgoing packet. This is why NAT hole punching works. If both end points are behind NAT and just assume that the link will work. Both can just start sending UDP packets to each other. The routers will add the connection state, and map the incoming packets to each endpoint.

Get random free opened port for tests

I'm running some integration tests with REST API service.
The problem is that sometimes hardcoded port isn't free at the moment the test starts for the next time. Because it was opened by previous test and isn't closed by the system yet.
I use OWIN, the application is shut down at the moment the next test starts.
Could you please suggest me a good way to determine a free port on the system without opening it in advance and then closing it? Or say that it's not possible.
Because it could be not freed by the system yet, just as it happens already.
As an alternative to TempoClick's answer, we can use the IPGlobalProperties.GetActiveTcpListeners() method to test if a port is available - without trying to open it in advance. GetActiveTcpListeners() returns all active TCP listeners on the system, and so we can use it to determine if a port is free or not.
public bool IsFree(int port)
{
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] listeners = properties.GetActiveTcpListeners();
int[] openPorts = listeners.Select(item => item.Port).ToArray<int>();
return openPorts.All(openPort => openPort != port);
}
Note that GetActiveTcpListeners() doesn't return listening UDP endpoints, but we can get them with GetActiveUdpListeners().
So, you can start with the default port (or select a random value) and keep incrementing until you find a free port with the IsFree method.
int NextFreePort(int port = 0)
{
port = (port > 0) ? port : new Random().Next(1, 65535);
while (!IsFree(port))
{
port += 1;
}
return port;
}
A simple test:
using System;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Linq;
class Test
{
static void Main(string[] args)
{
int port = 1000;
Console.WriteLine(IsFree(port));
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
server.Start();
Console.WriteLine(IsFree(port));
Console.WriteLine(NextFreePort(port));
}
static bool IsFree(int port)
{
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] listeners = properties.GetActiveTcpListeners();
int[] openPorts = listeners.Select(item => item.Port).ToArray<int>();
return openPorts.All(openPort => openPort != port);
}
static int NextFreePort(int port = 0) {
port = (port > 0) ? port : new Random().Next(1, 65535);
while (!IsFree(port)) {
port += 1;
}
return port;
}
}
A different approach is to use port zero. In this case, the system will select a random free port from the dynamic port range. We can get the number ot this port from the LocalEndpoint property.
TcpListener server = new TcpListener(IPAddress.Loopback, 0);
server.Start();
int port = ((IPEndPoint)server.LocalEndpoint).Port;
Console.WriteLine(port);
To get a free port
static int FreePort()
{
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
When using t.m.adam's
NextFreePort(...) method, the port may be free, but not permitted. In my case, this happened under Linux. The following method tests, whether the free port can actually be used:
static bool CanBindPort(int port)
{
try
{
var localEndPoint = new IPEndPoint(IPAddress.Any, port);
using var listener = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
}
catch
{
// e.g. because of "Permission denied" or other reason
return false;
}
return true;
}
This is, however, not the requested solution for "without opening the port in advance".
The following one-liner (taken from this SO post), uses Python to quickly open and close a socket on port 0. When you do this in Python, it automatically selects an open port, which gets printed out to the screen:
python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'

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

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.

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.

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