開發環境:Windows10
Qt版本:Qt5.11.0
此區域網路通信使用的是TCP傳輸控制協定,采用用戶端/伺服器模式,即C/S模式,使用QTcpSocket編寫用戶端,QTcpServer編寫伺服器,通過對端口的監聽,一旦發現用戶端的連接配接請求,就會發出相應的信号;用戶端一旦有資料到來也會發出信号,進行接收。
首先,來設計伺服器端,界面設計如下:
由于是和用戶端通信,此界面除了有伺服器的IP和端口外,還有用戶端的IP和端口,實作發送資訊給用戶端。
直接來看代碼,首先在.pro檔案裡添加網絡子產品
QT += core gui network
widget.h檔案代碼
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QNetworkInterface>
#include <QDebug>
#include <QMessageBox>
#include <QTcpSocket>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_But_serve_bound_clicked();
void on_Btn_socket_send_clicked();
void oneProcessNewConnection(); //新的連接配接信号函數
void oneProcessAcceptError(QAbstractSocket::SocketError err); //錯誤處理函數
void oneProcessDisconnected(); //用戶端斷開函數
void oneProcessReadyRead(); //讀取用戶端内容
void oneProcessConnected(); //用戶端連入函數
private:
Ui::Widget *ui;
QTcpServer *myServer; //定義服務對象
QList <QTcpSocket *> arrayClient; //儲存用戶端
QTcpSocket *client; //定義用戶端描述符
void InitServe(); //初始化伺服器函數
};
#endif // WIDGET_H
widget.cpp檔案代碼
#include "widget.h"
#include "ui_widget.h"
#define MAXNUM 100
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
InitServe();
}
Widget::~Widget()
{
delete ui;
}
//初始化函數
void Widget::InitServe()
{
myServer = new QTcpServer(this); //配置設定空間
}
//綁定槽函數實作
void Widget::on_But_serve_bound_clicked()
{
//方法一:通過程式周遊網卡IP
QString myAddr;
// QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); //傳回所有IP位址,然後進行周遊
// for(int i=0;i<ipAddressesList.length();i++)
// {
// QString myAddr;
// QHostAddress addr = ipAddressesList.at(i);
// qDebug() << addr.toString(); //列印傳回資訊
// if(addr.toString().contains("192.")) //篩選
// {
// myAddr = addr.toString();
// qDebug() <<myAddr;
// qDebug() << "***************";
// ui->Edit_serve_IP->setText(myAddr);
// }
// }
//方法二:手動設定IP
myAddr = ui->Edit_serve_IP->text(); //手動輸入IP到edit框
QString myPort = ui->Edit_serve_Port->text(); //手動設定端口
QString msg;
bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt()); //伺服器監聽綁定
if(!ret)
{
msg = "太可惜了,綁定失敗啦!";
}
else
{
msg = "哈哈哈,綁定成功啦,@OneStar!";
ui->But_serve_bound->setEnabled(false);
}
ui->textEdit_serve->setText(msg); //将資訊顯示在消息框
myServer->setMaxPendingConnections(MAXNUM); //設定監聽數量
connect(myServer,SIGNAL(newConnection()),this,SLOT(oneProcessNewConnection())); //建立新的連接配接信号
connect(myServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),this,SLOT(oneProcessAcceptError(QAbstractSocket::SocketError))); //錯誤處理
}
//建立連接配接信号函數
void Widget::oneProcessNewConnection()
{
client = myServer->nextPendingConnection(); //用戶端的連接配接,擷取用戶端描述符
arrayClient.append(client);
//用戶端斷開
connect(client,SIGNAL(disconnected()),this,SLOT(oneProcessDisconnected()));
//讀取用戶端内容
connect(client,SIGNAL(readyRead()),this,SLOT(oneProcessReadyRead()));
//用戶端的連入
connect(client,SIGNAL(connected()),this,SLOT(oneProcessConnected()));
}
//錯誤處理函數
void Widget::oneProcessAcceptError(QAbstractSocket::SocketError err)
{
qDebug() << err;
}
//用戶端斷開函數
void Widget::oneProcessDisconnected()
{
QTcpSocket *client = (QTcpSocket *)this->sender(); //強轉TCP類型
QString msg = QString("用戶端[%1:%2] 退出!").arg(client->peerAddress().toString()).arg(client->peerPort());
ui->textEdit_serve->append(msg); //顯示斷開資訊
//周遊删除對應用戶端
for(int i=0;i<arrayClient.length();i++)
{
if(arrayClient.at(i)->peerAddress() == client->peerAddress())
{
if(arrayClient.at(i)->peerPort() == client->peerPort())
{
arrayClient.removeAt(i);
break;
}
}
}
}
//讀取用戶端内容函數
void Widget::oneProcessReadyRead()
{
QTcpSocket *client = (QTcpSocket *)this->sender(); //強轉TCP類型
QString str1 = QString("用戶端[%1:%2] 說:").arg(client->peerAddress().toString()).arg(client->peerPort());
QString msg;
QString str2;
while(!client->atEnd()) //不到末尾是進行讀取内容
{
msg.append(QString(client->readAll()));
}
str2 = QString("%1%2").arg(str1).arg(msg);
ui->textEdit_serve->append(str2); //将讀取用戶端的内容顯示在edit資訊框
}
void Widget::oneProcessConnected()
{
QTcpSocket *client = (QTcpSocket *)this->sender();
QString msg = QString("用戶端[%1:%2] 連入!").arg(client->peerAddress().toString()).arg(client->peerPort());
ui->textEdit_serve->append(msg);
}
//點選槽函數實作,發送資訊給用戶端
void Widget::on_Btn_socket_send_clicked()
{
QString ip = ui->Edit_socket_IP->text(); //擷取IP
QString port = ui->Edit_socket_Port->text(); //擷取端口号
//周遊查找對應的客戶
for(int i=0;i<arrayClient.length();i++)
{
if(arrayClient.at(i)->peerAddress().toString() == ip)
{
if(arrayClient.at(i)->peerPort() == port.toUInt())
{
QString msg = ui->textEdit_socket->toPlainText(); //擷取發送消息
arrayClient.at(i)->write(msg.toUtf8()); //将消息發送出去
ui->textEdit_socket->clear(); //将消息框清空
break;
}
}
}
}
總結一下服務端的編寫步驟
1、使用QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)進行監聽綁定;
2、使用newConnection()信号函數建立連接配接,對用戶端進行斷開,讀取内容等一系列操作;
3、編寫發送槽函數,使用arrayClient.at()->write(msg.toUtf8())将消息發送給用戶端。
接下來是用戶端編寫實作:Qt實作簡易區域網路通信(二)