Qt怎么获取空闲端口号?这里给大家介绍一个通过Windows API来get的方法:
一、新建Qt控制台应用程序
这里需要使用到WS2_32.lib及IPHlpApi.Lib库文件,如我的这两个库文件的路径:
将64位的路径下的库文件拷贝到项目文件夹夹下。
二、修改项目配置
xxx.pro文件添加库文件,添加如下代码:
注意不用写文件后缀,-l后面拼接上库名。
三、设计接口
static QVector<uint16_t> GetAllTcpConnectionsPort() //获取所有已占用的TCP端口号
static QVector<uint16_t> GetAllUdpConnectionsPort()获取所有已占用的UDP端口号
QVector<uint16_t> FindAvailableTcpPort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)//查找可用的TPC端口
QVector<uint16_t> FindAvailableUdpPort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)//查找可用的UDP端口
QVector<uint16_t> FindAvailablePort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)//查找可用的端口
四、main.cpp代码如下(含接口设计)
#include <QCoreApplication>
#include <QDebug>
#include <Windows.h>
#include <WinSock.h>
#include <tcpmib.h>
#include <IPHlpApi.h>
#include <memory>
#include <algorithm>
//端口号取值范围【0-65535】,其中1023以前预留给了常用应用程序
//一般在1024之后取端口号
#define PORT_DOWN 1024 //起始端口号
#define PORT_UP 65535 //终止端口号
//获取所有已占用的TCP端口号
static QVector<uint16_t> GetAllTcpConnectionsPort()
{
QVector<uint16_t> ret;
ULONG size = 0;
GetTcpTable(NULL, &size, TRUE);
std::unique_ptr<char[]> buffer(new char[size]);
PMIB_TCPTABLE tcpTable = reinterpret_cast<PMIB_TCPTABLE>(buffer.get());
if (GetTcpTable(tcpTable, &size, FALSE) == NO_ERROR)
for (size_t i = 0; i < tcpTable->dwNumEntries; i++)
ret.push_back(ntohs((uint16_t)tcpTable->table[i].dwLocalPort));
std::sort(std::begin(ret), std::end(ret));
return ret;
}
//获取所有已占用的UDP端口号
static QVector<uint16_t> GetAllUdpConnectionsPort()
{
QVector<uint16_t> ret;
ULONG size = 0;
GetUdpTable(NULL, &size, TRUE);
std::unique_ptr<char[]> buffer(new char[size]);
PMIB_UDPTABLE udpTable = reinterpret_cast<PMIB_UDPTABLE>(buffer.get());
if (GetUdpTable(udpTable, &size, FALSE) == NO_ERROR)
for (size_t i = 0; i < udpTable->dwNumEntries; i++)
ret.push_back(ntohs((uint16_t)udpTable->table[i].dwLocalPort));
std::sort(std::begin(ret), std::end(ret));
return ret;
}
//查找可用的TPC端口
QVector<uint16_t> FindAvailableTcpPort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)
{
auto vec = GetAllTcpConnectionsPort();
QVector<uint16_t> availablePortVector;
//在端口区间检测端口是否在占用列表中,如果不在则表示当前的端口可用并返回
for (uint16_t port = begin; port != end; ++port)
if (!std::binary_search(std::begin(vec), std::end(vec), port))
{
static int i = 0;
availablePortVector.insert(i++,port);
}
return availablePortVector;
return availablePortVector;
}
//查找可用的UDP端口
QVector<uint16_t> FindAvailableUdpPort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)
{
auto vec = GetAllUdpConnectionsPort();
QVector<uint16_t> availablePortVector;
for (uint16_t port = begin; port != end; ++port)
if (!std::binary_search(std::begin(vec), std::end(vec), port))
{
static int i = 0;
availablePortVector.insert(i++,port);
}
return availablePortVector;
return availablePortVector;
}
//查找可用的端口
QVector<uint16_t> FindAvailablePort(uint16_t begin = PORT_DOWN, uint16_t end = PORT_UP)
{
auto vecTcp = GetAllTcpConnectionsPort(),
vecUdp = GetAllUdpConnectionsPort();
QVector<uint16_t> availablePortVector;
for (uint16_t port = begin; port != end; ++port)
if (!std::binary_search(std::begin(vecTcp), std::end(vecTcp), port) &&
!std::binary_search(std::begin(vecUdp), std::end(vecUdp), port))
{
static int i = 0;
availablePortVector.insert(i++,port);
}
return availablePortVector;
return availablePortVector;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WSADATA wsaData;//保存函数WSAStartup调用后返回的Windows Sockets数据
WORD wVersionRequested = MAKEWORD(1,2);//主版本号为1,副版本号为2,返回0x0201;
WSAStartup(wVersionRequested, &wsaData);
//打印出当前所有可用的TCP端口号
qDebug() << endl << "Tcp Available port : " << endl << FindAvailableTcpPort();
qDebug() << endl << "Udp Available port : " << endl << FindAvailableUdpPort();
qDebug() << endl << "Available port : " << endl << FindAvailablePort();
//解除与Socket库的绑定并且释放Socket库所占用的系统资源
WSACleanup();
return a.exec();
}