142

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);
Ali
  • 5,286
  • 9
  • 33
  • 36
  • 4
    What do you mean by "free" here? If you try to connect to it and fail, that probably means nothing was listening. – Jon Skeet Feb 20 '09 at 16:10
  • 2
    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 Feb 20 '09 at 16:13
  • What is the server you are trying to connect to? Did you write it, or is it an existing server? – grieve Apr 03 '09 at 19:53
  • 3
    As has been stated in many answers, you have everything backwards. Local ports and remote ports are two different things entirely. This answer in particular explains it well: http://stackoverflow.com/questions/570098/in-c-how-to-check-if-a-tcp-port-is-available/724022#724022 – bzlm Apr 09 '09 at 17:59
  • Why not just catch the exception eventually raised from the TcpClient constructor? i.e.: try { c = new TcpClient(ip, port); } catch(Exception){ //port is taken... } – adospace Sep 29 '20 at 11:50
  • see my answer to the similar question here: https://stackoverflow.com/a/76181957/13563751 – Szynkie May 08 '23 at 12:13

20 Answers20

252

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.
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
jro
  • 7,372
  • 2
  • 23
  • 36
  • 44
    Keep in mind that another process could bind to that port while you are checking. – Serguei Apr 06 '09 at 20:02
  • Good point, very possible. Not sure one can lock or mutex their way to exclusive access to a port. – jro Apr 06 '09 at 22:33
  • 3
    How is this relevant to the question? This answer deals with *local* ports, not *remote* ports. – bzlm Apr 09 '09 at 17:58
  • 7
    It's relevant in that it answers the OP's request. The local/remote difference notwithstanding (totally agree with you), the OP's requirement was to create a new TcpClient with a port that is "free". – jro Apr 09 '09 at 21:41
  • 10
    Note that this code only check active connections. The connections which don't have sent or received packets will not be listed. – JoeBilly Jun 17 '11 at 11:27
  • 42
    Compare the result of the code above to `netstat -a -b`. Notice that `LISTENING` connections are not present in the `GetActiveTcpConnections()`. You should also check in `System.Net.IPEndPoints[]` returned by `ipGlobalProperties.GetActiveTcpListeners();` – Mike de Klerk Feb 07 '13 at 13:26
  • 1
    You can create a TcpClient with a local port that is free by specifying zero as the local port. None of this is necessary, and it is liable to a major timing-window problem. – user207421 May 14 '15 at 22:44
  • 1
    @jro -- the `TcpClient` class will always use a port that is free (the port in the constructor that the op asked about is for the remote endpoint! -- local outgoing ports are always auto assigned by winsocks, and you do not have control over them!). -- This *is* useful for `TcpServer`, etc. -- but I'm not sure how useful it will be for whatever the heck the op is trying to do. – BrainSlugs83 Jan 25 '16 at 21:55
  • In UWP, this throws an exception https://github.com/dotnet/runtime/issues/24369 – Ben Jasperson Sep 28 '22 at 17:19
51

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • That's where I was going with it too. Someone is definitely confused here, and it's possible it me. – Moose Feb 20 '09 at 17:28
  • 3
    It is possible that the client requires a certain port too, but it's not common. – Dave Van den Eynde Apr 08 '09 at 07:03
  • @DaveVandenEynde that can only happen if the "client" is actually "serving" something on that particular port (making it a "server", at least for that port, as far as TCP is concerned). -- When you have a client TCP connection, you don't get to control the outgoing port. The TCP stack assigns you an outgoing port, and you don't have any control over it. – BrainSlugs83 Jan 25 '16 at 23:03
  • 1
    @BrainSlugs83 You most certainly can: http://stackoverflow.com/questions/2869840/is-there-a-way-to-specify-the-local-port-to-used-in-tcpclient – Dave Van den Eynde Jan 26 '16 at 09:37
  • 2
    This is a valid bit of code to check if the port is free. Just remember to Stop() the TcpListener in case it succeeds (unless you intend to use that same TcpListener object to start listening on the port). – bgh Oct 08 '19 at 05:38
19

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
17

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;
}
Melloware
  • 10,435
  • 2
  • 32
  • 62
  • You don't need this. Just specify port zero. – user207421 May 14 '15 at 22:44
  • The note in the source code comment : "This is the same information provided by the netstat command line application" -- is a lie. It does not provide the same information as the netstat command also provides the PID of the application using the port (`-anb`) and without any parameters it shows Foreign connection as well as state. – Kraang Prime May 02 '17 at 12:09
16
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..)

Indy9000
  • 8,651
  • 2
  • 32
  • 37
7

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.

sergtk
  • 10,714
  • 15
  • 75
  • 130
user336046
  • 79
  • 1
  • 1
7

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.

CCondron
  • 1,926
  • 17
  • 27
5

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
craftxbox
  • 220
  • 1
  • 3
  • 12
Simone
  • 1,418
  • 15
  • 22
5
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);
}
Learning
  • 8,029
  • 3
  • 35
  • 46
  • I am the one trying to connect to a socket. I have edited the question to make it more clear. – Ali Feb 20 '09 at 16:09
  • I like this code the best, this really opens up a TCP connection to a socket just to peek if someone is listening on the other end or not. And I think many people actually want this, when they want to "test if a port is open on a remote host". There is a bug however in the above code: if (sock.Connected == true) then the port is open for connections, some server-like software is listening there. If there's a SocketException with a 10061 ErrorCode (message "(0x80004005): No connection could be made because the target machine actively refused it" then the port is closed! – Csaba Toth Mar 19 '13 at 23:25
  • So it's the other way around then in the code snippet. Another note: if someone would try Dns.GetHostEntry in such test setup where you have virtual servers with only IP addresses, you gonna have an exception. – Csaba Toth Mar 19 '13 at 23:27
3

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.

Community
  • 1
  • 1
John Leidegren
  • 59,920
  • 20
  • 131
  • 152
3

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.

Tevo D
  • 3,351
  • 21
  • 28
3

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.

Joshua
  • 40,822
  • 8
  • 72
  • 132
2

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.

Moose
  • 5,354
  • 3
  • 33
  • 46
  • If my application try to connect using port 10 and another instance of my application try to connect using port 10 again it will fail because both applications can't send data using one port, when it comes to receiving data i.e. port 80 that is different – Ali Feb 20 '09 at 16:39
  • how is it different? what is listening on port 10 for your application? – Moose Feb 20 '09 at 16:48
  • if it fails when the second instance tries to connect, it is the listening application, not your application. – Moose Feb 20 '09 at 16:49
1
    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;
    }
Martin.Martinsson
  • 1,894
  • 21
  • 25
1

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;
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Mohsen
  • 4,049
  • 1
  • 31
  • 31
1

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}");
JasonJ
  • 51
  • 3
  • This is a great solution, unfortunately it's not available for Linux as it says "The information requested is unavailable on the current platform." – DARKGuy Jul 18 '22 at 03:11
1

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.

ya23
  • 14,226
  • 9
  • 46
  • 43
  • 5
    TOCTOU is YALAIHHOBIKTPBI (Yet Another Long Abbreviation I Haven't Heard Of, But I Know the Phenomena Behind It) – Csaba Toth Mar 19 '13 at 23:30
1

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.

Michał Piaskowski
  • 3,800
  • 2
  • 34
  • 46
  • That is good for checking a set of given sockets. The question is about just one socket (which port number maybe undetermined though (?)) – Csaba Toth Mar 19 '13 at 18:35
0
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.");
   }
 }
}
Pardeep Dhingra
  • 3,916
  • 7
  • 30
  • 56
  • 2
    When posting some code, try to elaborate on why it is the solution to the problem. Just code might be too little information and your answer risks being looked over. – Glubus Jan 08 '16 at 14:59
-2

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++;
    }
}
shakram02
  • 10,812
  • 4
  • 22
  • 21