diff --git a/src/libs/utils/tcpportsgatherer.cpp b/src/libs/utils/tcpportsgatherer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2a89f17ef2b46b606e7c9ead3c7f66ec5327bf06
--- /dev/null
+++ b/src/libs/utils/tcpportsgatherer.cpp
@@ -0,0 +1,260 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "tcpportsgatherer.h"
+#include "qtcassert.h"
+#include <QFile>
+#include <QStringList>
+#include <QProcess>
+
+#ifdef Q_OS_WIN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <iphlpapi.h>
+#endif
+
+namespace Utils {
+namespace Internal {
+
+class TcpPortsGathererPrivate
+{
+public:
+    TcpPortsGathererPrivate(TcpPortsGatherer::ProtocolFlags protocolFlags)
+        : protocolFlags(protocolFlags) {}
+
+    TcpPortsGatherer::ProtocolFlags protocolFlags;
+    PortList usedPorts;
+
+    void updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags);
+    void updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags);
+    void updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags);
+};
+
+#ifdef Q_OS_WIN
+template <typename Table, ULONG (__stdcall *Func)(Table*, PULONG, BOOL) >
+QSet<int> usedTcpPorts()
+{
+    Table *table = static_cast<Table*>(malloc(sizeof(Table)));
+    DWORD dwSize = sizeof(Table);
+
+    // get the necessary size into the dwSize variable
+    DWORD dwRetVal = Func(table, &dwSize, false);
+    if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
+        free(table);
+        table = static_cast<Table*>(malloc(dwSize));
+    }
+
+    // get the actual data
+    QSet<int> result;
+    dwRetVal = Func(table, &dwSize, false);
+    if (dwRetVal == NO_ERROR) {
+        for (quint32 i = 0; i < table->dwNumEntries; i++) {
+            quint16 port = ntohs(table->table[i].dwLocalPort);
+            if (!result.contains(port))
+                result.insert(port);
+        }
+    } else {
+        qWarning() << "TcpPortsGatherer: GetTcpTable failed with" << dwRetVal;
+    }
+
+    free(table);
+    return result;
+}
+#endif
+
+void TcpPortsGathererPrivate::updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags)
+{
+#ifdef Q_OS_WIN
+    QSet<int> ports;
+
+    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
+        ports.unite(usedTcpPorts<MIB_TCPTABLE, GetTcpTable>());
+    if (protocolFlags & TcpPortsGatherer::IPv6Protocol)
+        ports.unite(usedTcpPorts<MIB_TCP6TABLE, GetTcp6Table>());
+
+    foreach (int port, ports) {
+        if (!usedPorts.contains(port))
+            usedPorts.addPort(port);
+    }
+#endif
+    Q_UNUSED(protocolFlags);
+}
+
+void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags)
+{
+    QStringList filePaths;
+    if (protocolFlags & TcpPortsGatherer::IPv4Protocol)
+        filePaths.append(QLatin1String("/proc/net/tcp"));
+    if (protocolFlags & TcpPortsGatherer::IPv6Protocol)
+        filePaths.append(QLatin1String("/proc/net/tcp6"));
+
+    foreach (const QString &filePath, filePaths) {
+        QFile file(filePath);
+        if (!file.open(QFile::ReadOnly | QFile::Text)) {
+            qWarning() << "TcpPortsGatherer: Cannot open file"
+                       << filePath << ":" << file.errorString();
+            continue;
+        }
+
+        if (file.atEnd()) // read first line describing the output
+            file.readLine();
+
+        static QRegExp pattern(QLatin1String("^\\s*" // start of line, whitespace
+                                             "\\d+:\\s*" // integer, colon, space
+                                             "[0-9A-Fa-f]+:" // hexadecimal number (ip), colon
+                                             "([0-9A-Fa-f]+)"  // hexadecimal number (port!)
+                                             ));
+        while (!file.atEnd()) {
+            QByteArray line = file.readLine();
+            if (pattern.indexIn(line) != -1) {
+                bool isNumber;
+                quint16 port = pattern.cap(1).toUShort(&isNumber, 16);
+                QTC_ASSERT(isNumber, continue);
+                if (!usedPorts.contains(port))
+                    usedPorts.addPort(port);
+            } else {
+                qWarning() << "TcpPortsGatherer: File" << filePath << "has unexpected format.";
+                continue;
+            }
+        }
+    }
+}
+
+// Only works with FreeBSD version of netstat like we have on Mac OS X
+void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags)
+{
+    QStringList netstatArgs;
+
+    netstatArgs.append(QLatin1String("-a"));     // show also sockets of server processes
+    netstatArgs.append(QLatin1String("-n"));     // show network addresses as numbers
+    netstatArgs.append(QLatin1String("-p"));
+    netstatArgs.append(QLatin1String("tcp"));
+    if (protocolFlags != TcpPortsGatherer::AnyIPProcol) {
+        netstatArgs.append(QLatin1String("-f")); // limit to address family
+        if (protocolFlags == TcpPortsGatherer::IPv4Protocol)
+            netstatArgs.append(QLatin1String("inet"));
+        else
+            netstatArgs.append(QLatin1String("inet6"));
+    }
+
+    QProcess netstatProcess;
+    netstatProcess.start(QLatin1String("netstat"), netstatArgs);
+    if (!netstatProcess.waitForFinished(30000)) {
+        qWarning() << "TcpPortsGatherer: netstat did not return in time.";
+        return;
+    }
+
+    QList<QByteArray> output = netstatProcess.readAllStandardOutput().split('\n');
+    foreach (const QByteArray &line, output) {
+        static QRegExp pattern(QLatin1String("^tcp[46]+" // "tcp", followed by "4", "6", "46"
+                                             "\\s+\\d+"           // whitespace, number (Recv-Q)
+                                             "\\s+\\d+"           // whitespace, number (Send-Q)
+                                             "\\s+(\\S+)"));       // whitespace, Local Address
+        if (pattern.indexIn(line) != -1) {
+            QString localAddress = pattern.cap(1);
+
+            // Examples of local addresses:
+            // '*.56501' , '*.*' 'fe80::1%lo0.123'
+            int portDelimiterPos = localAddress.lastIndexOf(".");
+            if (portDelimiterPos == -1)
+                continue;
+
+            localAddress = localAddress.mid(portDelimiterPos + 1);
+            bool isNumber;
+            quint16 port = localAddress.toUShort(&isNumber);
+            if (!isNumber)
+                continue;
+
+            if (!usedPorts.contains(port))
+                usedPorts.addPort(port);
+        }
+    }
+}
+
+} // namespace Internal
+
+
+/*!
+  \class Utils::TcpPortsGatherer
+
+  \brief Gather the list of local TCP ports already in use.
+
+  Query the system for the list of local TCP ports already in use. This information can be used
+  to select a port for use in a range.
+*/
+
+TcpPortsGatherer::TcpPortsGatherer(TcpPortsGatherer::ProtocolFlags protocolFlags)
+    : d(new Internal::TcpPortsGathererPrivate(protocolFlags))
+{
+    update();
+}
+
+TcpPortsGatherer::~TcpPortsGatherer()
+{
+    delete d;
+}
+
+void TcpPortsGatherer::update()
+{
+    d->usedPorts = PortList();
+
+#if defined(Q_OS_WIN)
+    d->updateWin(d->protocolFlags);
+#elif defined(Q_OS_LINUX)
+    d->updateLinux(d->protocolFlags);
+#else
+    d->updateNetstat(d->protocolFlags);
+#endif
+}
+
+PortList TcpPortsGatherer::usedPorts() const
+{
+    return d->usedPorts;
+}
+
+/*!
+  Select a port out of \a freePorts that is not yet used.
+
+  Returns the port, or 0 if no free port is available.
+  */
+quint16 TcpPortsGatherer::getNextFreePort(PortList *freePorts)
+{
+    QTC_ASSERT(freePorts, return 0);
+    while (freePorts->hasMore()) {
+        const int port = freePorts->getNext();
+        if (!d->usedPorts.contains(port))
+            return port;
+    }
+    return 0;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/tcpportsgatherer.h b/src/libs/utils/tcpportsgatherer.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ad6e24bf2022c1ac17ef9ce64995804e6699d7c
--- /dev/null
+++ b/src/libs/utils/tcpportsgatherer.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef TCPPORTSGATHERER_H
+#define TCPPORTSGATHERER_H
+
+#include "portlist.h"
+
+namespace Utils {
+namespace Internal {
+class TcpPortsGathererPrivate;
+}
+
+class QTCREATOR_UTILS_EXPORT TcpPortsGatherer
+{
+public:
+    enum NetworkLayerProtocol {
+        IPv4Protocol = 0x1,
+        IPv6Protocol = 0x2,
+        AnyIPProcol = IPv4Protocol | IPv6Protocol
+    };
+    Q_DECLARE_FLAGS(ProtocolFlags, NetworkLayerProtocol)
+
+    TcpPortsGatherer(ProtocolFlags flags);
+    ~TcpPortsGatherer();
+
+    void update();
+
+    PortList usedPorts() const;
+    quint16 getNextFreePort(PortList *port);
+
+private:
+    Internal::TcpPortsGathererPrivate *d;
+};
+
+} // namespace Utils
+
+#endif // TCPPORTSGATHERER_H
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index ffe02726533e428c7abb99085f356a967e82b26a..a81c43cc13bbe720cf28ba18e19f6585e76ffc4d 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -94,7 +94,8 @@ SOURCES += $$PWD/environment.cpp \
     $$PWD/persistentsettings.cpp \
     $$PWD/completingtextedit.cpp \
     $$PWD/json.cpp \
-    $$PWD/portlist.cpp
+    $$PWD/portlist.cpp \
+    $$PWD/tcpportsgatherer.cpp
 
 win32 {
     SOURCES += \
@@ -205,7 +206,8 @@ HEADERS += \
     $$PWD/json.h \
     $$PWD/multitask.h \
     $$PWD/runextensions.h \
-    $$PWD/portlist.h
+    $$PWD/portlist.h \
+    $$PWD/tcpportsgatherer.h
 
 FORMS += $$PWD/filewizardpage.ui \
     $$PWD/projectintropage.ui \
diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro
index 0a1888c1138b88957cb5cc0c2393f1e2f9ca2fd0..88417900406c76f525bced4847e66e58df7d6cd2 100644
--- a/src/libs/utils/utils.pro
+++ b/src/libs/utils/utils.pro
@@ -20,3 +20,5 @@ SOURCES += \
     proxyaction.cpp
 
 win32: LIBS += -lUser32
+# PortsGatherer
+win32: LIBS += -liphlpapi -lWs2_32
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index 64291c9c6b8f64a2d8e72320bbeb9442fd51ea63..d97e483651a977dd33e701f96846c91254498e2b 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -14,7 +14,7 @@ DynamicLibrary {
 
     Properties {
         condition: qbs.targetOS == "windows"
-        cpp.dynamicLibraries: ["User32.lib"]
+        cpp.dynamicLibraries: ["User32.lib", "iphlpapi.lib", "Ws2_32.lib"]
     }
 
     Depends { name: "cpp" }
@@ -127,6 +127,8 @@ DynamicLibrary {
         "submitfieldwidget.h",
         "synchronousprocess.cpp",
         "synchronousprocess.h",
+        "tcpportsgatherer.cpp",
+        "tcpportsgatherer.h",
         "textfileformat.cpp",
         "textfileformat.h",
         "treewidgetcolumnstretcher.cpp",
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 5e4e50c7ae21cc752f4f26321cb0af1a088cc710..29f79d6c4226d38da49e0fb8456d3184f8e91569 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -5,7 +5,8 @@ cplusplus-frontend \
 fakevim \
 debugger \
 preprocessor \
-subdir_proparser
+subdir_proparser \
+utils
 
 unix {
 #   Uses popen
diff --git a/tests/manual/utils/tcpportsgatherer/main.cpp b/tests/manual/utils/tcpportsgatherer/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..df553b63bfaa8d781d3aaa0c1ea5dbe8423f36fc
--- /dev/null
+++ b/tests/manual/utils/tcpportsgatherer/main.cpp
@@ -0,0 +1,36 @@
+#include <QCoreApplication>
+#include <utils/tcpportsgatherer.h>
+#include <QDebug>
+#include <QStringList>
+
+using namespace Utils;
+int main()
+{
+    qDebug() << "Used TCP Ports (IP4):";
+
+    TcpPortsGatherer ip4Ports(TcpPortsGatherer::IPv4Protocol);
+    qDebug() << ip4Ports.usedPorts().toString();
+
+    qDebug() << "Used TCP Ports (IP6):";
+    TcpPortsGatherer ip6Ports(TcpPortsGatherer::IPv6Protocol);
+    qDebug() << ip6Ports.usedPorts().toString();
+
+    qDebug() << "All Used TCP Ports:";
+    TcpPortsGatherer ipPorts(TcpPortsGatherer::AnyIPProcol);
+    qDebug() << ipPorts.usedPorts().toString();
+
+    qDebug() << "Getting a few ports ...";
+    PortList portList = PortList::fromString("10000-10100");
+    QStringList ports;
+    for (int i = 0; i < 10; ++i) {
+        quint16 port = ipPorts.getNextFreePort(&portList);
+        Q_ASSERT(!ipPorts.usedPorts().contains(port));
+        Q_ASSERT(port >= 10000);
+        Q_ASSERT(port < 10100);
+        QString portStr = QString::number(port);
+        Q_ASSERT(!ports.contains(portStr));
+        ports.append(QString::number(port));
+    }
+    qDebug() << ports.join(", ");
+    return 0;
+}
diff --git a/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro
new file mode 100644
index 0000000000000000000000000000000000000000..87d05661e95789cecdd03dd187fee3bf930db15a
--- /dev/null
+++ b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro
@@ -0,0 +1,27 @@
+TEMPLATE = app
+TARGET = tcpportsgatherer
+
+QT = core gui
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += console
+CONFIG -= app_bundle
+
+include(../../../../qtcreator.pri)
+include(../../../../src/rpath.pri)
+
+
+INCLUDEPATH += ../../../../src/libs
+UTILSDIR = ../../../../src/libs/utils
+
+DEFINES += QTCREATOR_UTILS_STATIC_LIB
+
+HEADERS += \
+    $${UTILSDIR}/portlist.h \
+    $${UTILSDIR}/tcpportsgatherer.h
+SOURCES += \
+    $${UTILSDIR}/portlist.cpp \
+    $${UTILSDIR}/tcpportsgatherer.cpp
+
+win32:LIBS += -liphlpapi -lWs2_32
+SOURCES += main.cpp
diff --git a/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.qbp b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.qbp
new file mode 100644
index 0000000000000000000000000000000000000000..e909add0d79e6a9657488e2648162ab8353a5eba
--- /dev/null
+++ b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.qbp
@@ -0,0 +1,24 @@
+import qbs.base 1.0
+
+Application {
+    name: "tcpportsgatherer"
+
+    files: [
+        "main.cpp",
+        "../../../../src/libs/utils/portlist.cpp",
+        "../../../../src/libs/utils/portlist.h",
+        "../../../../src/libs/utils/tcpportsgatherer.cpp",
+        "../../../../src/libs/utils/tcpportsgatherer.h"
+    ]
+
+    cpp.includePaths: [ "../../../../src/libs" ]
+    cpp.defines: [ "QTCREATOR_UTILS_STATIC_LIB" ]
+
+    Properties {
+        condition: qbs.targetOS == "windows"
+        cpp.dynamicLibraries: [ "iphlpapi.lib", "Ws2_32.lib" ]
+    }
+
+    Depends { name: "cpp" }
+    Depends { name: "Qt"; submodules: ["gui"] }
+}
diff --git a/tests/manual/utils/utils.pro b/tests/manual/utils/utils.pro
new file mode 100644
index 0000000000000000000000000000000000000000..a4899f90bb6c4c89cfaadc5a0a64a383f05364f9
--- /dev/null
+++ b/tests/manual/utils/utils.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS = tcpportsgatherer