吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4029|回复: 11
收起左侧

[其他原创] QT开发TCP协议的通信软件

  [复制链接]
seattle^-^ 发表于 2019-12-10 21:28
本帖最后由 seattle^-^ 于 2019-12-10 21:52 编辑

大二课设课程结束了,来总结一下这次的实战QT开发。虽然代码不精致,但是也是笔者一个月的成果。喜欢的来看啊
先上两张本地测试的图片

首先是客户端 QQ图片20191210204614.png

然后是服务端 QQ图片20191210204543.png




然后接下来是效果图,服务端跟客户端放在一张图里了,图标取自网络,如有侵权,联系笔者。


QQ图片20191210204719.png

然后接下来是测试图,时间紧迫,客户端只设置了一个账号,输入账号密码之后进入到此界面


QQ图片20191210205641.png




好了,这些是我们小组的项目。写起来也很简单啊,采用QT开发C++语言。


QT开发的这种软件还是相对比较简单的啊。
记录一下代码:客户端采用了QT提供的信号与槽,对各种点击事件发出信号,代码段做出反应。
客户端的对话框代码段对信息文本的处理,来判断服务器转发的信息与自己的信息来做出不同的文本显示:
[C++] 纯文本查看 复制代码
void qtchatmessage::paintEvent(QPaintEvent *)    //画家
{
    QPainter painter(this);    //画家
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);//消锯齿
    painter.setPen(Qt::NoPen);   //画笔
    painter.setBrush(QBrush(Qt::gray));  //画刷


    if(m_userType == User_Type::User_He) { // 用户
        //头像
        painter.drawPixmap(m_iconLeftRect, m_leftPixmap);


        //框加边
        QColor col_KuangB(234, 234, 234);
        painter.setBrush(QBrush(col_KuangB));
        painter.drawRoundedRect(m_kuangLeftRect.x()-1,m_kuangLeftRect.y()-1,m_kuangLeftRect.width()+2,m_kuangLeftRect.height()+2,4,4);
        //框
        QColor col_Kuang(255,255,255);
        painter.setBrush(QBrush(col_Kuang));
        painter.drawRoundedRect(m_kuangLeftRect,4,4);


        //三角
        QPointF points[3] = {
            QPointF(m_sanjiaoLeftRect.x(), 30),
            QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 25),
            QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 35),
        };
        QPen pen;
        pen.setColor(col_Kuang);
        painter.setPen(pen);
        painter.drawPolygon(points, 3);


        //三角加边
        QPen penSanJiaoBian;
        penSanJiaoBian.setColor(col_KuangB);
        painter.setPen(penSanJiaoBian);
        painter.drawLine(QPointF(m_sanjiaoLeftRect.x() - 1, 30), QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 24));
        painter.drawLine(QPointF(m_sanjiaoLeftRect.x() - 1, 30), QPointF(m_sanjiaoLeftRect.x()+m_sanjiaoLeftRect.width(), 36));


        //内容
        QPen penText;
        penText.setColor(QColor(51,51,51));
        painter.setPen(penText);
        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        painter.setFont(this->font());
        painter.drawText(m_textLeftRect, m_msg,option);
    }  else if(m_userType == User_Type::User_Me) { // 自己
        //头像
        painter.drawPixmap(m_iconRightRect, m_rightPixmap);             //画头像加头像的框架。框加图


        //框
        QColor col_Kuang(75,164,242);      //颜料
        painter.setBrush(QBrush(col_Kuang));    //设置画刷,参数为颜色
        painter.drawRoundedRect(m_kuangRightRect,4,4);    //画给定矩形框的圆角


        //三角
        QPointF points[3] = {
            QPointF(m_sanjiaoRightRect.x()+m_sanjiaoRightRect.width(), 30),   //给定的坐标构造点
            QPointF(m_sanjiaoRightRect.x(), 25),
            QPointF(m_sanjiaoRightRect.x(), 35),
        };
        QPen pen;             //画笔
        pen.setColor(col_Kuang);
        painter.setPen(pen);   //把pen给painter
        painter.drawPolygon(points, 3);  //绘制数组中的这三个点


        //内容
        QPen penText;     //创建画笔
        penText.setColor(Qt::white);
        painter.setPen(penText);    //笔给画家
        QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);    //选项    左和水平居中
        option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);   //设置换行模式
        painter.setFont(this->font());     //为画家选择字体
        painter.drawText(m_textRightRect,m_msg,option);   //往矩形框中按照option画入m_msg文本
    }
}





接下来是客户端的送槽函数,用来获取输入的文本,对文本向绘图事件虚函数传递参数,然后向对话框显示文本。
[C++] 纯文本查看 复制代码
void aWidget::on_pushButton_clicked()    //发送按钮的槽函数
{
    QString str = ui->textEdit_2->toPlainText();   //获取发送区的内容
    if(str == "")return;
    tcpsocket->write(str.toUtf8().data());        //利用通信套接字向发送缓冲区写入数据
    ui->textEdit_2->clear();       //清空发送区
    qtchatmessage* messageW = new qtchatmessage(ui->listWidget->parentWidget()); //创建气泡
    QListWidgetItem* item = new QListWidgetItem(ui->listWidget);  //创建小部件,选项控件
    dealMessage(messageW, item, str, qtchatmessage::User_Me);   //处理创建的气泡
    ui->listWidget->setCurrentRow(ui->listWidget->count()-1);   //移动到最后一行
}




然后客户端设置事件过滤器,来过滤键盘操作,设置快捷键回车来点击发送按钮
[C++] 纯文本查看 复制代码
bool aWidget::eventFilter(QObject *target, QEvent *event){   //事件过滤器,不设置事件过滤器会被系统的函数自动过滤
    if(target == ui->textEdit_2)
    {
        if(event->type() == QEvent::KeyPress)         //按键盘事件
        {
             QKeyEvent *k = static_cast<QKeyEvent *>(event);
             if(k->key() == Qt::Key_Return||k->key() == Qt::Key_Enter)          //回车
             {
                 aWidget::on_pushButton_clicked();
                 return true;
             }
        }
    }
    return QWidget::eventFilter(target,event);
}



接受函数采用QT提供的虚函数接受消息处理
[C++] 纯文本查看 复制代码
connect(tcpsocket, &QTcpSocket::readyRead,
            [=]()
            {
                QByteArray str = tcpsocket->readAll();   //获取对方发送的数据
                QString string = static_cast<QString>(str);   //强转
                if(record[0] == 'n'){
                    if(string == "yes"){record[0] = 'y'; w1.hide();this->show();}else return;
                }
                qtchatmessage* messageW = new qtchatmessage(ui->listWidget->parentWidget()); //创建气泡
                QListWidgetItem* item = new QListWidgetItem(ui->listWidget);  //创建小部件,选项控件
                dealMessage(messageW, item, str, qtchatmessage::User_He);   //处理创建的气泡
                ui->listWidget->setCurrentRow(ui->listWidget->count()-1);   //移动到最后一行
            } );   //接受数据



客户端大致就这些。接下来总结一下服务端:
变量列表:
[C++] 纯文本查看 复制代码
QTcpServer *tcpserver;
    QTcpSocket *tcpsocket[13];
    char flag[13];   //判断是否连接
    char record[13];  //判断是否登录
    void initMumber();
    void initMumber_1();
    void dealConnect();
    void dealMessage(int i);
    void dealRecord(int i);   //处理登录




创建了十三个通信套接字,一个监听套接字。标志位变量。首先初始化各变量,包括监听套接字。
[C++] 纯文本查看 复制代码
void aWidget::initMumber(){
    tcpserver = new QTcpServer(this);
    tcpserver->listen(QHostAddress::Any, 6666);
    aWidget::initMumber_1();
}


void aWidget::initMumber_1(){
    for(int j = 0;j<13;j++){
        flag[j] = 'n';
        record[j] = 'n';
        tcpsocket[j] = nullptr;
        }
}



服务端的监听套接字,监听新连接,触发信号调用处理函数,设置标志位变量为已连接。
[C++] 纯文本查看 复制代码
void aWidget::dealConnect(){    //处理连接
    for(int i = 0;i < 13;i++){
        if(flag[i] == 'n'){
          flag[i] = 'y';
          tcpsocket[i] = tcpserver->nextPendingConnection();   //连接客户端
          QString ip = tcpsocket[i]->peerAddress().toString();  //打印信息
          quint16 port = tcpsocket[i]->peerPort();
          QString temp = QString("[%1:%2]:接入服务").arg(ip).arg(port);
          ui->textEdit->append(temp);   //向服务器显示连接信息
          connect(tcpsocket[i], &QTcpSocket::readyRead,[=](){aWidget::dealMessage(i);});  //监听是否来信息  //dealMessage函数的参数必须传局部变量,不能传全局变量。
          break;     //必须有break,否则会把通信套接字循环完的。                                               //随着i的变化Lambda表达式的函数体随着变化
        }
    }
    int b;    //不能写进for里面,因为有的退出了,套接字就不能用了
    for (b = 0;b < 13;b++) {
        if(flag[b] == 'n')break;
    }
    if(b == 13)
        ui->textEdit->append("已经没有可用的套接字了");


}



入监听接受信息函数来分发信息,达到服务器转发信息的目的
[C++] 纯文本查看 复制代码
void aWidget::dealMessage(int i){    //把消息分发给所有在线客户
      if(record[i] == 'n'){
          aWidget::dealRecord(i);
          return;
      }
      QByteArray array = tcpsocket[i]->readAll();    //获取内容
      for(int j = 0;j<13;j++)
      {
          if(flag[j] != 'n'&&i != j)
          {
              tcpsocket[j]->write(array);
          }
      }
}



基本上TCP通信采用QT开发的基本流程就这些,还有一些细节的处理,项目中对气泡的处理参考了一下网络上的代码。其他调用函数我没写进去,需要的小伙伴说一声,我抽空上传到百度网盘。由于项目代码中涉及到一些隐私就没全部上传,所有的图片均取自于网络,如有侵权,联系笔者,立刻删除。新人第一次发帖,大家多多照顾。目前大二小菜鸟,希望和大家共同进步。加油啦~。

代码如果哪里有问题,大佬勿喷,笔者还是大二在校生。联系笔者,一定跟大家交流,共同进步。


要乖,那些错过的,咱们不要了。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zhaopython 发表于 2020-9-9 11:39
如果改成有客户端请求链接,服务端再创建套接字监听更合理,客户端断开后删除对应套接字,这样改一下理论上就可以监听无数个端口,在你这个基础上加点代码就可以了,小小建议
clickto 发表于 2020-6-17 20:56
 楼主| seattle^-^ 发表于 2020-6-19 14:40
小鱼又咸又辣 发表于 2020-6-29 09:06
写的不错
 楼主| seattle^-^ 发表于 2020-6-29 10:55

尴尬尴尬      
白竹 发表于 2020-7-6 22:01
哥  有代码吗
senlinyiye 发表于 2020-7-6 23:11
大哥,厉害了
hhxxttxs 发表于 2020-8-3 20:26
好样的,继续努力!
大侠在路上 发表于 2020-9-9 12:26
感谢楼主分享,我觉得已经很棒了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-23 22:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表