Day26Qt实现QTcpServer-2022-01-06

Qt Network(一)tcp服务器

简介TCP

TCP协议,传输控制协议,是一个用于数据传输的底层的网络协议,多个互联网协议包括FTP,HTTP协议都是基于TCP协议的。TCP是一个面向数据流和连接的可靠的传输协议。QTcpSocket类为TCP提供了一个接口,可以用其实现POP3、SMTP等标准的网络协议,也可以实现自定义的网络协议。连接的一端是客户端,另一端是服务器端,也就是C/S模型。

步骤与目标

使用Qt network做一个TCP服务器,可以接收客户端的访问请求,能够传输数据。首先创建QTcpServer类对象,用于管理服务器;调用listen方法,监听对应地址对应端口,使本主机作为服务器,使得程序能够监听某一端口的连接情况;当有客户端发出连接请求时,服务器对象会发出newConnection()信号,监听过程出错时,服务器会发出acceptError()信号;连接建立后出现错误会发出disconnected()信号,有数据来临会发出readyread()信号,当需要发送数据到客户端的时候,调用write方法即可。

总结与思考

1.使用network模块,记得在pro文件中添加network模块。
2.我在实践中遇到了每次点击发送按钮,连接就断开的情况,在网络中查询答案,未果,最终确定由于本地电脑加密软件的原因造成,因此当出现这个问题的时候,关闭防火墙,关闭杀毒软件,关闭与网络相关的应用进程,多从本地配置的角度考虑。
3.思考如何做一个文件服务器,可以接收客户端上传数据。
4.使用utf8可以发送汉字,对方也使用utf8则可以正确接收。汉字的发送与接收与编码方式有关,可以使用QTextcodec做。

效果

与网口助手调试结果如下,收发数据正常,网口调试助手下载
Day26Qt实现QTcpServer-2022-01-06_第1张图片
与Qt开发客户端测试结果如下,汉字也收发正常,
Day26Qt实现QTcpServer-2022-01-06_第2张图片

代码

ui文件

Day26Qt实现QTcpServer-2022-01-06_第3张图片

main文件

#include "mainwindow.h"
#include 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include 
#include 
#include 
#include 
#include 
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void doProcessNewConnection();
    void doProcessAcceptError(QAbstractSocket::SocketError);
    void doProcessDisconnected();
    void doProcessReadyRead();
//    void doProcessConnect();
    void on_band_Btn_clicked();
    void on_tran_Btn_clicked();
private:
    Ui::MainWindow *ui;
    QTcpServer *myServer;
    QTcpSocket *client;
    QList<QTcpSocket *>arrayClient;
    void Init();
};
#endif // MAINWINDOW_H

.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#define MAXNUM 100

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    Init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::Init()
{
    myServer = new QTcpServer(this);
    this->setWindowTitle("服务器");
}
//绑定按钮槽函数
void MainWindow::on_band_Btn_clicked()
{
   
    //方法1 :通过程序遍历网卡ip
//    QListaddrs = QNetworkInterface::allAddresses();
//    for (int i = 0; i 
//        QHostAddress addr = addrs.at(i);
//        qDebug()<
//        if(addr.toString().contains("192.")){
//            myAddr = addr.toString();
//            break;
//        }
//    }
    //方法2: 手动设置ip
    QString myAddr = ui->serverIP->text();
    QString myPort = ui->serverPort->text();
    QString msg;
    bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt());//监听对应地址对应端口,使本主机作为服务器
    if(!ret){
        msg = "绑定失败!";
    }
    else{
        msg = "绑定成功!";
        ui->band_Btn->setEnabled(false);
    }
    ui->textEdit->append(msg);

    myServer->setMaxPendingConnections(MAXNUM);//设置等待连接队列中的最大数量,默认30
    connect(myServer,SIGNAL(newConnection()),this,SLOT(doProcessNewConnection()));//监听之后,新的客户端接入会触发此信号
    connect(myServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),
            this,SLOT(doProcessAcceptError(QAbstractSocket::SocketError)));//监听过程出错会进入这个槽

}
//绑定发送按钮槽函数
void MainWindow::on_tran_Btn_clicked()
{
    //获取界面ip地址和端口信息
    QString ip = ui->clientIP->text();
    QString port = ui->clientPort->text();
    //查找对应的客户
    for (int i = 0; i < arrayClient.length(); ++i) {
        if(arrayClient.at(i)->peerAddress().toString() == ip){//找到对应的ip
            if(arrayClient.at(i)->peerPort() == port.toUInt()){//找到对应端口
                QString msg = ui->textEdit_2->toPlainText();
                arrayClient.at(i)->write(msg.toUtf8());//使用utf8可以发送汉字,对方也使用utf8则可以正确接收
                ui->textEdit_2->clear();
                break;
            }
        }
    }
}
void MainWindow::doProcessNewConnection()
{
  client =  myServer->nextPendingConnection();//建立连接,获取客户端对象
  QString msg = QString("客户端[%1:%2] 连入!").arg(client->peerAddress().toString()).arg(client->peerPort());
  ui->textEdit->append(msg);
  arrayClient.append(client);//存储已接入的客户端
  //客户端断开
connect(client,SIGNAL(disconnected()),this,SLOT(doProcessDisconnected()));//建立间接之后,监听断开信号
  //读取内容
  connect(client,SIGNAL(readyRead()),this,SLOT(doProcessReadyRead()));//准备接收数据
}
void MainWindow::doProcessAcceptError(QAbstractSocket::SocketError err)
{
    qDebug()<<err;
}
void MainWindow::doProcessDisconnected()
{
    QTcpSocket *client = (QTcpSocket *)this->sender();
    QString msg = QString("客户端[%1:%2] 退出!").arg(client->peerAddress().toString()).arg(client->peerPort());
    ui->textEdit->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);
            }
        }
    }
}
void MainWindow::doProcessReadyRead()
{
    QTcpSocket *client = (QTcpSocket *)this->sender();
    QString str1 = QString("客户端[%1:%2] 说:").arg(client->peerAddress().toString()).arg(client->peerPort());//返回客户端的ip与port
    QString msg;
    QString str2;
    while(!client->atEnd()){
        msg.append(QString(client->readAll()));//接收数据
    }
    str2 = QString("%1%2").arg(str1).arg(msg);
    ui->textEdit->append(str2);
}

你可能感兴趣的:(Qt积累——基础篇,服务器,tcp/ip,网络,qt)