尚未崩坏 发表于 2024-8-19 15:24:35

Qt框架下服务器的实现

一、媒介

Qt框架提供了QTcpServe和QTcpSocket两种类实现TCP协议的相关毗连,TCP协议不再过多赘述,以下主要讲述自机服务器和自机客户端的毗连实现TCP协议通讯的详细方式。
二、根本功能介绍

利用Qt网络模块之前必要在.pro文件种加入network
服务器端

绑定端口,并通过信号判断新连入客户机,同时输出相关内容,同时通过断连信号举行客户端的删除。
收信功能绑定读取信号槽函数,对所带数据举行读取显示。
发信功能找到对应的客户机地址和端口举行发信
客户机端

毗连端口
收信功能绑定读取信号槽函数
发信功能直接将发送数据写入设备
三、详细原理和代码实现

在.pro文件中加入network
QT       += core gui network 初始化并分配指针空间
void Widget::Init()
{
    myClient = new QTcpSocket(this);

}
服务器端实现

1.ui设计

搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行绑定和发送
https://i-blog.csdnimg.cn/direct/f1ca6c1346cd40b088578281f1a22bbc.png
2.IP绑定

通过listen方法指示服务器侦听地址、地址和端口端口上的传入毗连。如果端口为 0,则自动选择端口。如果 address 为 QHostAddress::Any,则服务器将侦听所有网络接口。
setEnable设置按钮是否可以利用
setMaxPendingConnection设置最大挂起客户机数量
void Widget::on_btn_bind_clicked()
{
    QString myAddr;
    //手动设置ip
    myAddr = ui->ledit_serv_addr->text();
    QString myPort = ui->ledit_serv_port->text();
    QString msg;
    bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt());
    if(!ret)
    {
      msg = "绑定失败";
    }
    else
    {
      msg = "绑定成功";
      ui->btn_bind->setEnabled(false);
    }
    ui->textEdit->append(msg);
    myServer->setMaxPendingConnections(MAXNUM);
    connect(myServer,SIGNAL(newConnection()),this,SLOT(doProcessNewConnection()));
    connect(myServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),
            this,SLOT(doProcessAcceptError(QAbstractSocket::SocketError)));

} 3.客户端连入

nextPendingConnection(),用于等候并担当下一个挂起的毗连。当一个客户端请求毗连时,服务器会将该毗连挂起,等候服务器担当毗连。nextPendingConnection()函数会阻塞当前线程,直到有一个毗连被担当。一旦有毗连被担当,会返回一个QTcpSocket对象。
此时对客户端的IP地址和端标语举行读取并显示
void Widget::doProcessNewConnection()
{
    client = myServer->nextPendingConnection();
    arrayClient.append(client);
    QString msg = QString("客户端[%1:%2] 连入!")
            .arg(client->peerAddress().toString())
            .arg(client->peerPort());
    ui->textEdit->append(msg);
    //客户端断开
    connect(client,SIGNAL(diconnected()),this,SLOT(doProcessDiconnected()));
    //读取内容
    connect(client,SIGNAL(readyRead()),this,SLOT(doProcessReadyRead()));
} 4.客户端退出

当客户端退出时,通过sender返回指向发送信号的对象的指针,同时遍历客户机列表删除对应的客户端
void Widget::doProcessDiconnected()
{
    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);
                break;
            }
      }
    }
} 5.吸取信息

利用readyRead()信号,每当有新数据可用于从器件的当前读取通道读取时,该信号就会发出一次。将该信号内容举行循环读取并举行显示。
void Widget::doProcessReadyRead()
{
    QTcpSocket *client = (QTcpSocket *)this->sender();
    QString str1 = QString(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->append(str2);
} 6.发送信息

读取输入的客户端IP和端口信息,遍历客户端列表,找到对应的客户端通过write举行数据写入。
void Widget::on_btn_send_clicked()
{
    QString ip = ui->ledit_client_ip->text();
    QString port = ui->ledit_client_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_2->toPlainText();\
                arrayClient.at(i)->write(msg.toUtf8());
                ui->textEdit_2->clear();
                break;
            }
      }
    }
} 客户机端实现

1.ui设计

搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行毗连和发送
https://i-blog.csdnimg.cn/direct/52760edd1be64056abc2eb38c060e540.png
2.服务器毗连

connectTohost对指定的IP地址和端标语举行毗连,同时绑定四信号和槽函数
void Widget::on_btn_bind_clicked()
{
    QString servIp = ui->ledit_serv_addr->text();
    QString servPort = ui->ledit_serv_port->text();
    myClient->connectToHost(QHostAddress(servIp),servPort.toUInt());
    connect(myClient,SIGNAL(connected()),this,SLOT(doProcessConnected()));
    connect(myClient,SIGNAL(readyRead()),this,SLOT(dorProcessReadyRead()));
    connect(myClient,SIGNAL(disconnected()),this,SLOT(doProcessDisconnected()));
    connect(myClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(doProcessError(QAbstractSocket::SocketError)));

} 3.信息吸取

readyRead信号举行读取,与服务器端相同
void Widget::dorProcessReadyRead()
{
    QString msg,str1,str2;
    str1 = QString(" 服务器[%1:%2] 说:")
            .arg(myClient->peerAddress().toString())
            .arg(myClient->peerPort());
    while(!myClient->atEnd())
    {
      str2.append(QString(myClient->readAll()));
    }
    msg = QString("%1%2").arg(str1).arg(str2);
    ui->textEdit->append(msg);
} 4.信息发送

write举行写入,与服务器端相同
void Widget::on_btn_send_clicked()
{
    QString msg = ui->textEdit_2->toPlainText();
    int ret = myClient->write(msg.toUtf8());
    if(ret<=0)
      return;
    ui->textEdit_2->clear();
} 四、关于端标语和地址

windows操纵系统下,可以通过cmd举行IP地址和端标语的查询
IP地址查询:ipconfig
一般利用IPV4右侧的IP地址
端标语查询:netstat -na
TCP对应的端标语,此中LISTENING代表监听状态,ESTABLISHED代表已毗连,TIME_WAIT代表结束访问,CLOSE_WAIT代表等候制止。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Qt框架下服务器的实现