QT/基于TCP的服务端实现

代码

widget.cpp

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ,p(new QTcpServer(this))//给服务器指针申请空间
{
    ui->setupUi(this);
}

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


void Widget::on_pushButton_clicked()//启动服务器按钮对应槽函数
{
    //获取ui界面的端口号
    quint16 port=ui->lineEdit->text().toUInt();//将获取的行编辑器的字符转为无符号整型
    //设置服务器监听
    if(p->listen(QHostAddress::Any,port)){
        QMessageBox::information(this,"提示","服务器启动成功");
    }else{
        QMessageBox::information(this,"提示","服务器启动失败");
        return;
    }
    //此时服务器已建立监听,如客户端发来连接,服务器自动发送一个newConnection()信号
    //将该信号连接到自定义的槽函数中,处理逻辑
    connect(p,&QTcpServer::newConnection,this,&Widget::newConnection);
}

void Widget::newConnection()//newConnection信号对应槽函数实现
{
    //获取客户端套接字
    QTcpSocket *s=p->nextPendingConnection();
    //将客户端套接字放入容器
    socketList.push_back(s);
    //程序运行至此,说明服务器与客户端建立了连接
    //如果客户端向服务器发来数据,客户端就会自动发送一个readyRead信号(客户端套接字,QtcpScoket),就可以将该信号连接到自定义的槽函数,读取数据
    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead);
}

void Widget::readyRead()//readyRead信号对应槽函数实现
{
    //遍历客户端容器,移除无效(断开连接)客户端
    for(int i=0;i<socketList.count();i++){
                            //获取容器元素个数的函数
        //判读连接状态,state函数返回值是一个枚举,值为0,表示未连接
        if(socketList.at(i)->state()==0){
            socketList.removeAt(i);//删除该元素
        }
    }
    //遍历客户端,判断那个客户端有数据待读
    for(int i=0;i<socketList.count();i++){
            //bytesAvailable,数据的字节
            if(socketList.at(i)->bytesAvailable()!=0){
                //读取数据
                QByteArray msg=socketList.at(i)->readAll();
                //将读取的数据放到ui界面
                ui->listWidget->addItem(QString::fromLocal8Bit(msg));//fromLocal8Bit字节转为QString
                //将发送的消息转发给其他客户端
                for(int i=0;i<socketList.count();i++){
                    socketList.at(i)->write(msg);
                }
            }
        }
   // p->close();//关闭服务器
}

widget.ui

cpp 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>470</width>
    <height>439</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <widget class="QListWidget" name="listWidget">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>20</y>
     <width>441</width>
     <height>321</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>380</y>
     <width>81</width>
     <height>31</height>
    </rect>
   </property>
   <property name="text">
    <string>端口号:</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="lineEdit">
   <property name="geometry">
    <rect>
     <x>70</x>
     <y>380</y>
     <width>221</width>
     <height>31</height>
    </rect>
   </property>
  </widget>
  <widget class="QPushButton" name="pushButton">
   <property name="geometry">
    <rect>
     <x>310</x>
     <y>380</y>
     <width>141</width>
     <height>31</height>
    </rect>
   </property>
   <property name="text">
    <string>启动服务器</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

main.cpp

cpp 复制代码
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>//服务器类
#include <QMessageBox>
#include <QTcpSocket>//套记字类
#include <QList>//链表容器类,是一个类模板
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();
public slots:
    void newConnection();//newConnection()槽函数
    void readyRead();//readyRead()信号槽函数

private:
    Ui::Widget *ui;
    //实例化一个服务器指针
    QTcpServer *p;
    //定义存放客户端套接字的容器
    QList<QTcpSocket *> socketList;
};
#endif // WIDGET_H
相关推荐
luoyayun3614 分钟前
Qt + FFmpeg 音频工具:重采样实现
qt·ffmpeg·重采样
2zcode16 分钟前
项目文档:基于MATLAB图像处理的饮料瓶灌装液位检测系统设计与实现
开发语言·图像处理·matlab
月疯33 分钟前
np.where()[0]的用法
开发语言·python·numpy
z落落39 分钟前
C#五大加密算法(AES、DES、MD5、RSA、SHA)
开发语言·c#
namexingyun42 分钟前
Scaling Law bug实战启示:从“虚胖“到“精瘦“的算力效率革命
开发语言·网络·人工智能·bug·ai编程
KaMeidebaby43 分钟前
卡梅德生物技术快报|纳米抗体技术全套实操流程:AFB1 全合成文库淘选 + 分子对接定点突变参数手册
人工智能·python·tcp/ip·算法·机器学习
hnxaoli1 小时前
统信小程序(十六)xls转xlsx
开发语言·python·小程序
孝顺的书包1 小时前
将《C# 调用非托管程序》一文中最后一种方法修改如下(篇幅原因简化了注释):
开发语言·c#
云栖梦泽在1 小时前
原生 IP、机房 IP、住宅 IP、广播 IP 有何不同?从网络身份到 ASN 识别的技术科普
网络·网络协议·tcp/ip·性能优化
不知名的老吴1 小时前
浅谈:编程语言中的那些「锁」事(二)
java·开发语言