一相关函数(QT += network)

1主机(本机)信息查询

一 QHostInfo类:

1 localHostName()函数:返回本机主机名

无参数,返回值QString类型的主机名称
1
QString hostName=QHostInfo::localHostName();//本地主机名

2 fromName(QString &name)函数:返回指定的主机名的IP地址 参数:QString类型的主机名 返回值:指定的主机名QHostInfo类型的IP地址

1
QHostInfo   hostInfo=QHostInfo::fromName(hostName);

3 addresses()函数:返回与hostName()主机关联的IP地址列表[即QHostInfo类型转化成QList类型方便提取] 无参数,返回QList类型的ip列表(就是个数组每一条都是QHostAddress类型)

1
QList<QHostAddress> addList=hostInfo.addresses();

4 QList 提取每条QHostAddress类型的数据:at(i)protocol()函数可以显示QHostAddress类型中的地址是ipv4还是ipv6toString()可以把QHostAddress类型转换成String类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 //遍历查询ip
//非空时定义一个QHostAddress类型的变量来接收QList<QHostAddress>类型的ip列表的第i条数据
if (!addList.isEmpty())
//获取列表中有几条并借此循环
for (int i=0;i<addList.count();i++)
{ //addList.at(i)取出QList容器中第i条数据
QHostAddress aHost=addList.at(i);
//protocol()函数可以显示QHostAddress类型中的地址是ipv4还是ipv6
if (QAbstractSocket::IPv4Protocol==aHost.protocol())
{
// QHostAddress类型可以toString()转换成String类型
localIP=aHost.toString();
break;
}
}

二 QNetworkInterface类:

1. allInterfaces()函数:返回主机上所有接口的网络列表

   无参数,返回值QList<QNetworkInterface>(QNetworkInterface类型的数组)
   返回值包含QString类型的:
              接口名称 :通过QNetworkInterfac的对象.humanReadableName()
              硬件地址 :通过QNetworkInterfac的对象.hardwareAddress()
            QList<QNetworkAddressEntry>类型的:
              ip地址列表(包含ip,mac地址和 ): 通过QNetworkInterfac的对象.addressEntries()
2. .ip().toString()函数: 把QNetworkAddressEntry类型里的IP转化为String
3.  .netmask().toString()函数:把QNetworkAddressEntry类型里的物理mac地址转化为String
4.  .broadcast.toString()函数:把QNetworkAddressEntry类型里的广播地址转化为String


2.实现过程(服务端)

ui comboIP:监听地址
actStart:开始监听按钮
spinPort:监听端口按钮
btnSend:发送按钮
editMsg:消息发送文本框

1. 在mainwindow.h中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    #include    <QTcpSocket>
#include <QLabel>
private:
QLabel *LabListen;//状态栏标签(显示是否监听成功)
QLabel *LabSocketState;//状态栏标签(显示套接字状态)

QTcpServer *tcpServer; //TCP服务器(实例化一个服务器对象)

QTcpSocket *tcpSocket;//TCP通讯的Socket(实例化一个套接字)

QString getLocalIP();//获取本机IP地址(写一个获取本地ip的函数)
private slots:
//自定义槽函数
//一旦有新的连接并成功连接,QTcpServer类实例化的对象就会自动产生newConnection()信号
void onNewConnection();//QTcpServer的newConnection()信号
// 套接字状态改变执行的
void onSocketStateChange(QAbstractSocket::SocketState socketState);
// 客户端启动连接时服务器该执行的
void onClientConnected(); //Client Socket connected
//客户端关掉连接时服务器该执行的
void onClientDisconnected();//Client Socket disconnected
//读取socket传入的数据
void onSocketReadyRead();//读取socket传入的数据
//UI生成的
void on_actStart_triggered();

void on_actStop_triggered();

void on_actClear_triggered();

void on_btnSend_clicked();

void on_actHostInfo_triggered();

2. 在mainwindow.cpp中(#include )

实现获取本地ip: 编写 getLocalIP()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
QString MainWindow::getLocalIP()
{//获取本机IPv4地址
QString hostName=QHostInfo::localHostName();//本地主机名
QHostInfo hostInfo=QHostInfo::fromName(hostName);
QString localIP="";
//一个容器
QList<QHostAddress> addList=hostInfo.addresses();//
//判段是否为空
if (!addList.isEmpty())
for (int i=0;i<addList.count();i++)
{
QHostAddress aHost=addList.at(i);
//筛选ipv4类型的
if (QAbstractSocket::IPv4Protocol==aHost.protocol())
{
localIP=aHost.toString();
break;
}
}
//返回ip地址
return localIP;
}

构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//建立一个文本框名字为 LabListen,初始打印"监听状态"
LabListen=new QLabel("监听状态:");
//设置文本框(LabListen)的最小宽度
LabListen->setMinimumWidth(150);
//把文本框(LabListen)添加到ui中
ui->statusBar->addWidget(LabListen);
//建立一个文本框名字为 LabSocketState,初始打印"Socket状态:"
LabSocketState=new QLabel("Socket状态:");
//设置文本框(LabSocketState)的最小宽度
LabSocketState->setMinimumWidth(200);
//把文本框(LabSocketState)添加到ui中
ui->statusBar->addWidget(LabSocketState);
//得到本机ip
QString localIP=getLocalIP();//本机IP
//设置窗口标题为本机ip
this->setWindowTitle(this->windowTitle()+"----本机IP:"+localIP);
//显示本机ip到comboIP控件
ui->comboIP->addItem(localIP);
//实例化一个服务器
tcpServer=new QTcpServer(this);
//(服务器开始监听后收到信号会自动连接,成功后会自动产生newConnection()信号)一旦连接服务器对象连接成功执行槽函数onNewConnectio()
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}

编写服务器监听函数 on_actStart_triggered();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void MainWindow::on_actStart_triggered()
{//开始监听
//获取本地ip
QString IP=ui->comboIP->currentText();//IP地址
//获取自己填写的端口
quint16 port=ui->spinPort->value();//端口
//通过ip生成一个QHostAddress类型的ip
QHostAddress addr(IP);
//服务器监听此地址和此端口
tcpServer->listen(addr,port);
// tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
ui->plainTextEdit->appendPlainText("**开始监听...");
// 显示服务器地址
ui->plainTextEdit->appendPlainText("**服务器地址:"
+tcpServer->serverAddress().toString());
//显示服务器端口
ui->plainTextEdit->appendPlainText("**服务器端口:"
+QString::number(tcpServer->serverPort()));
//开始监听按钮不能点击
ui->actStart->setEnabled(false);
// 停止按钮可以点击
ui->actStop->setEnabled(true);
//文本显示"监听状态:正在监听"
LabListen->setText("监听状态:正在监听");
}

编写客户端启动连接时服务器该执行的函数onClientConnected()

1
2
3
4
5
6
7
8
9
//只打印信息
void MainWindow::onClientConnected()
{
ui->plainTextEdit->appendPlainText("**client socket connected");
//通过传入的socket取出客户端地址并显示
ui->plainTextEdit->appendPlainText("**peer address:"+ tcpSocket->peerAddress().toString());
// 通过传入的socket取出客户端端口并显示
ui->plainTextEdit->appendPlainText("**peer port:"+ QString::number(tcpSocket->peerPort()));
}

编写客户端断开连接时服务器该执行的函数onClientDisconnected()

1
2
3
4
5
6
7
void MainWindow::onClientDisconnected()
{
ui->plainTextEdit->appendPlainText("**client socket disconnected");
//删除Socket
tcpSocket->deleteLater();
// deleteLater();//QObject::deleteLater();
}

编写客户端与服务器成功建立新连接时服务器该执行的函数onNewConnection()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void MainWindow::onNewConnection()
{

//创建socket
tcpSocket = tcpServer->nextPendingConnection(); //创建socket
//
connect(tcpSocket, SIGNAL(connected()),
this, SLOT(onClientConnected()));
onClientConnected();//
//连接断开时Socket自动产生disconnected()信号
//客户端断开连接时服务器执行槽函数onClientDisconnected()
connect(tcpSocket, SIGNAL(disconnected()),
this, SLOT(onClientDisconnected()));
//socket状态改变时Socket自动产生stateChanged信号
//参数QAbstractSocket::SocketState socketState自动改变
//socket状态改变时服务器该执行槽函数onSocketStateChange(QAbstractSocket::SocketState)
connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
//建立了新连接,执行槽函数 onSocketStateChange更改里面的值
onSocketStateChange(tcpSocket->state());
//完成连接后一旦Socket里背写入信息自动产生readyRead()信号 执行槽函数onSocketReadyRead()读Socket里的信息
connect(tcpSocket,SIGNAL(readyRead()),
this,SLOT(onSocketReadyRead()));
}

编写客户端与服务器socket状态改变该执行的函数onSocketStateChange(QAbstractSocket::SocketState socketState)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void MainWindow::onSocketStateChange(QAbstractSocket::SocketState socketState)
{//一旦socket状态变化时参数QAbstractSocket::SocketState socketState自动改变
//socket状态变化时
switch(socketState)
{
case QAbstractSocket::UnconnectedState:
//无连接
LabSocketState->setText("scoket状态:UnconnectedState");
break;
//正在查询
case QAbstractSocket::HostLookupState:
LabSocketState->setText("scoket状态:HostLookupState");
break;
//正在连接
case QAbstractSocket::ConnectingState:
LabSocketState->setText("scoket状态:ConnectingState");
break;
//连接成功
case QAbstractSocket::ConnectedState:
LabSocketState->setText("scoket状态:ConnectedState");
break;
//边界状态
case QAbstractSocket::BoundState:
LabSocketState->setText("scoket状态:BoundState");
break;
//关闭状态
case QAbstractSocket::ClosingState:
LabSocketState->setText("scoket状态:ClosingState");
break;
//监听状态
case QAbstractSocket::ListeningState:
LabSocketState->setText("scoket状态:ListeningState");
}
}

编写自动读取Socket存放的消息的函数onSocketReadyRead()

1
2
3
4
5
6
void MainWindow::onSocketReadyRead()
{//读取缓冲区行文本
//如果能读一行,就读一行
while(tcpSocket->canReadLine())
ui->plainTextEdit->appendPlainText("[in] "+tcpSocket->readLine());
}

编写服务器停止监听函数 on_actStop_triggered();

1
2
3
4
5
6
7
8
9
10
11
12
void MainWindow::on_actStop_triggered()
{ //tcpServer正在监听
if (tcpServer->isListening())
{ //停止监听
tcpServer->close();
//打开开始监听按钮
ui->actStart->setEnabled(true);
//关闭停止监听按钮
ui->actStop->setEnabled(false);
LabListen->setText("监听状态:已停止监听");
}
}

编写发送函数 on_btnSend_clicked()//收发协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void MainWindow::on_btnSend_clicked()
{//发送一行字符串,以换行符结束
//获取输入文本框的内容进行缓冲(msg就是缓冲)
QString msg=ui->editMsg->text();
//显示文本
ui->plainTextEdit->appendPlainText("[out] "+msg);
//清空输入
ui->editMsg->clear();
//定位光标
ui->editMsg->setFocus();
//把msg(缓冲)里的内容转换成Utf8
QByteArray str=msg.toUtf8();
//添加换行符以便识别输入结束
str.append('\n');//添加一个换行符(必须)
//把消息写入Socket
tcpSocket->write(str);
}

3.实现过程(客户端)

ui comboServer:服务器地址文本框(里面是自己填的不是传输得到的)
actConnect:连接服务器按钮
spinPort:需要连接的服务器端口文本框((里面是自己填的不是传输得到的))
actDisconnect:断开服务器按钮
btnSend:发送按钮
editMsg:消息发送文本框

1. 在mainwindow.h中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include    <QTcpSocket>
#include <QLabel>
private:
QTcpSocket *tcpClient; //使用socket实例化一个里客户端对象
QLabel *LabSocketState; //状态栏标签(显示套接字状态)
QString getLocalIP();//获取本机IP地址
protected:
void closeEvent(QCloseEvent *event);
private slots:
//自定义槽函数
//客户端连接成功执行的函数
void onConnected();
//客户端断开执行的函数
void onDisconnected();
// 套接字状态改变执行的
void onSocketStateChange(QAbstractSocket::SocketState socketState);
//读取socket传入的数据
void onSocketReadyRead();
//ui生成的
void on_actConnect_triggered();

void on_actDisconnect_triggered();

void on_actClear_triggered();

void on_btnSend_clicked();

2. 在mainwindow.cpp中

#include <QHostAddress>
#include <QHostInfo>)

实现获取本地ip: 编写 getLocalIP()

1
与上面的一样

构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//使用socket实例化一个里客户端对象(客户端本身就是个socket)
//创建socket变量
tcpClient=new QTcpSocket(this);
//建立一个文本框名字为 LabSocketState,初始打印"Socket状态:"
LabSocketState=new QLabel("Socket状态:");//状态栏标签
//设置文本框(LabSocketState)的最小宽度
LabSocketState->setMinimumWidth(250);
//把文本框(LabSocketState)添加到ui中
ui->statusBar->addWidget(LabSocketState);
//得到本机ip
QString localIP=getLocalIP();//本机IP
this->setWindowTitle(this->windowTitle()+"----本机IP:"+localIP);


//连接成功自动产生connected()信号,执行onConnected()槽函数
connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
//连接失败自动产生disconnected()信号,执行onDisconnected()槽函数
connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
//连接状态改变自动产生stateChanged(QAbstractSocket::SocketState)信号,执行onSocketStateChange(QAbstractSocket::SocketState))槽函数
connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
// socket里有消息可以读时自动产生readyRead()信号,执行onSocketReadyRead()槽函数
connect(tcpClient,SIGNAL(readyRead()),
this,SLOT(onSocketReadyRead()));

}

编写客户端按下启动连接时该执行的函数on_actConnect_triggered()

1
2
3
4
5
6
7
8
9
10
11
void MainWindow::on_actConnect_triggered()
{//连接到服务器
//获取comboServer文本框里填写的服务器地址
QString addr=ui->comboServer->currentText();
//获取spinPort文本框里填写的服务器端口
quint16 port=ui->spinPort->value();
//客户端根据地址和端口连接到主机(qt自带的)
//套接字实例化的客户端使用qt的connectToHost函数可以自动连接到某个服务器
tcpClient->connectToHost(addr,port);

}

编写客户端无法连接时该执行的函数onDisconnected()

1
2
3
4
5
6
7
//自动的
void MainWindow::onDisconnected()
{//disConnected()信号槽函数
ui->plainTextEdit->appendPlainText("**已断开与服务器的连接");
ui->actConnect->setEnabled(true);
ui->actDisconnect->setEnabled(false);
}

编写客户端成功连接时该执行的函数onConnected()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//自动的
void MainWindow::onConnected()
{ //connected()信号槽函数
ui->plainTextEdit->appendPlainText("**已连接到服务器");
//打印服务器的地址(peer代表同类,连接成功后服务器和客户端就是一对同类)
ui->plainTextEdit->appendPlainText("**peer address:"+
tcpClient->peerAddress().toString());
// 打印服务器的端口(peer代表同类)
ui->plainTextEdit->appendPlainText("**peer port:"+
QString::number(tcpClient->peerPort()));
// 使能按钮
ui->actConnect->setEnabled(false);
ui->actDisconnect->setEnabled(true);
}

编写客户端按下断开连接时该执行的函数on_actDisconnect_triggered()

1
2
3
4
5
6
7
void MainWindow::on_actDisconnect_triggered()
{//断开与服务器的连接
//判断(socket实例化的)客户端状态:(自动的)
if (tcpClient->state()==QAbstractSocket::ConnectedState)
// 客户段断开与主机的联系(qt自带disconnectFromHost())
tcpClient->disconnectFromHost();
}

编写客户端自动读取socket里的消息的函数onSocketReadyRead()

1
2
3
4
5
6
void MainWindow::onSocketReadyRead()
{//readyRead()信号槽函数
//如果socket里有消息可以读
while(tcpClient->canReadLine())
ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine());
}

编写发送函数 on_btnSend_clicked()//收发协议

1
2
3
4
5
6
7
8
9
10
11
void MainWindow::on_btnSend_clicked()
{//发送数据
QString msg=ui->editMsg->text();
ui->plainTextEdit->appendPlainText("[out] "+msg);
ui->editMsg->clear();
ui->editMsg->setFocus();

QByteArray str=msg.toUtf8();
str.append('\n');
tcpClient->write(str);
}

编写清空文本函数on_actClear_triggered()

1
2
3
4
void MainWindow::on_actClear_triggered()
{
ui->plainTextEdit->clear();
}

总结

服务端(QTcpServer *tcpServer; //TCP服务器(实例化一个服务器对象))

1.先获取本机ip

2.服务器监听本机ip和某个端口(自己写的):tcpServer->listen(addr,port);

3.服务器开始监听后收到信号会自动连接,成功后会自动产生newConnection()信号)一旦连接服务器对象连接成功执行槽函数onNewConnectio()

1.建立服务器的socket:tcpSocket = tcpServer->nextPendingConnection();
2.自动连接成功后服务器的socket自动产生connected()信号执行槽函数onNewConnectio()
3.连接断开时服务器Socket自动产生disconnected()信号执行槽函数onClientDisconnected()
4.socket状态改变时Socket自动产生stateChanged信号执行槽函数onSocketStateChange
5.完成连接后一旦Socket里写入信息自动产生readyRead()信号 执行槽函数onSocketReadyRead()读Socket里的信息
6.发送消息就是往socket里写数据: tcpSocket->write(str);

4.停止监听 :tcpServer->close();

客户端(QTcpSocket *tcpClient; //使用socket实例化一个里客户端对象)

1.使用socket实例化一个里客户端对象(客户端本身就是个socket)tcpClient=new QTcpSocket(this);
2.获取本机ip编写
3.客户端根据地址和端口(自己写的要连接的服务器ip和端口)连接到主机(qt自带的):套接字实例化的客户端使用qt的connectToHost函数可以自动连接到某个服务器
4.自动连接成功后客户端自动产生connected()信号执行槽函数onConnected()
5.完成连接后一旦Socket里写入信息自动产生readyRead()信号 执行槽函数onSocketReadyRead()读Socket里的信息
6.连接失败自动产生disconnected()信号,执行onDisconnected()槽函数
7.连接状态改变自动产生stateChanged(QAbstractSocket::SocketState)信号,执行onSocketStateChange(QAbstractSocket::SocketState))槽函数
8.发送消息就是往socket里写数据:tcpClient->write(str);
9.停止连接: 客户段断开与主机的联系(qt自带disconnectFromHost()):tcpClient->disconnectFromHost();

注意:

    服务端的ip是获取本机ip得到的,端口自己写的;
    客户端要连接哪个服务器的哪个端口是自己写的 :
    建立连接后由于是同类了,可以通过套接字里的peer查看对方的ip和端口;
    服务器查看客户端的:
    IP: tcpSocket->peerAddress().toString() 
    端口:QString::number(tcpSocket->peerPort())
    客户端查看服务器的:
    ip:    tcpClient->peerAddress().toString()
    端口:QString::number(tcpClient->peerPort())

源码:

链接:https://pan.baidu.com/s/1xqtD4-d9SbWwVlFMMrLxEg?pwd=sjii
提取码:sjii