qt网络编程

2021/7/14 20:06:11

本文主要是介绍qt网络编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

网络编程

Socket

qt下的socket

qt的TCP连接过程

TCP服务端给客户端传文件举例:

qt的UDP

qt的UDP单播举例:

UDP的广播与组播(多播)


网络编程

三个要素:IP地址、端口号和通信协议

IP地址:网络中的计算机使用IP地址来进行唯一标识,IP地址有IPv4和IPv6两种类型。IPv4采用十进制或二进制表示形式,十进制是一种比较常用的表示形式,如192.158.147.3。IPv6采用十六进制表示形式

端口号:计算机中的应用程序的一个整数数字标号,用来区分不同的应用程序

0 ~ 1024 为被系统使用或保留的端口号,0 ~ 65535为有效的端口号,也就是说我们要对一些程序定义端口号的时候,要选择1024 ~ 65535范围内的整数数字。

MySQL的端口号是3306,SQLServer的端口号是1433,Oracle的端口号是1521。

通信协议就是网络通信中的规则,分为TCP协议(面向连接的)和UDP协议(面向传输数据)两种

Socket

又叫“套接字”,它是计算机之间进行通信的一种约定或一种方式

通过 socket 这种约定,计算机可以接受其他计算机的数据,或者向其他计算机发送数据,里面有很多特殊的函数,是对其他计算机文件的读写操作

“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
即socket是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
Socket()函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

qt下的socket

TCP一般发文件,音频等,UDP一般发文字

QT       += network

LINUX下的TCP:

在LINUX下进行网络编程,我们可以使用LINUX提供的统一的套接字接口。但是这种方法牵涉到太多的结构体,比如IP地址,端口转换等。QT中提供的SOCKET完全使用了类的封装机制,使用户不需要接触底层的各种结构体操作。而且它采用QT本身的信号和槽机制,使编写的程序更容易理解。

qt的TCP连接过程

不管谁发送信息,成功后,对方的通信套接字触发readyRead()

TCP服务端给客户端传文件举例:

传文件流程图

 

 

server  ui 如下:

public:
void sendData();//发数据

private:
    QTcpServer *tcpServer;//监听套接字
    QTcpSocket *tcpSocket;//通信套接字
    QFile file;//文件对象
    QString filename;
    qint64 fileSize;
    qint64 sendSize;//已经发送文件的大小
    QTimer timer;//定时器

构造函数中

    
    tcpServer =new QTcpServer(this);
    tcpServer->listen(QHostAddress::Any,8888);//监听所有网址,设置server的端口8888
    
//连接成功自动触发newConnection
connect(tcpServer,&QTcpServer::newConnection,
            [=]()
    {
        tcpSocket =tcpServer->nextPendingConnection();//获取连接进来的socket
        QString ip=tcpSocket->peerAddress().toString();
        qint16 port =tcpSocket->peerPort();
        QString temp =QString("[%1:%2]:zhaoyi成功连接").arg(ip).arg(port);
        ui->textEditread->setText(temp);   //显示对方的ip和端口       
    }
            );
      //关闭定时器,发数据
       connect(&timer,&QTimer::timeout,
                [=]()
       {
             timer.stop();
              sendData();
        }
           );


}
//选文件
void server::on_pushButtonxuanwj_clicked()
{
    QString filepath=QFileDialog::getOpenFileName(this,"open","../");
    if(filepath.isEmpty()==false)//如果选择路径有效
    {
        //初始化
        filename.clear();
        fileSize=0;
        //获取文件信息
        QFileInfo info(filepath);
        filename=info.fileName();
        fileSize=info.size();

        sendSize=0;//发送文件的大小

        file.setFileName(filepath);//指定文件名

        bool isok=file.open(QIODevice::ReadOnly);//只读打开
        if(isok==false)
        {
            qDebug()<<"只读失败";
        }
        ui->textEdit->append(filepath);//提示文件路径
    }
    else
    {
        qDebug()<<"读文件失败";
    }
}

//发文件
void server::on_pushButtonxuan_clicked()
{
    //先发文件头信息   文件名##文件大小
    QString head=QString("%1##%2").arg(filename).arg(fileSize);
    qint64 len=tcpSocket->write(head.toUtf8());

    if(len>0)//如果头文件信息发送成功
    {
        timer.start(100);//间隔一定时间,发真正的文件,防止TCP黏包
    }
    else
    {
        qDebug()<<"head发送失败";
        file.close();
    }
}
void server::sendData()
{
    qint64 len=0;
    do
    {
        char buf[4*1024]={0};//发的大小
        len=0;

        //读多少,发多少
        len=file.read(buf,sizeof(buf));
        len=tcpSocket->write(buf,len);

        sendSize+=len;//累计
    }while(len>0);//判断读完

        if(sendSize == fileSize)
        {
            ui->textEdit->append("文件发送完毕");
            file.close();

            tcpSocket->disconnectFromHost();
            tcpSocket->close();
        }
}

client ui 如下:

private:
    QTcpSocket *tcpSocket;
    QFile file;//文件对象
    QString filename;
    qint64 fileSize;
    qint64 recvSize;//已经接受文件的大小
    bool isStart;

 

    tcpSocket=new QTcpSocket(this);
    isStart=true;
    recvSize=0;

    connect(tcpSocket,&QTcpSocket::readyRead,
            [=]()
    {
        QByteArray buf=tcpSocket->readAll();//取出所有内容
        if(isStart==true)
        {
            isStart=false;
            //解析头文件信息
            /*section的功能就是从一段字符串中拿出某一段连续的部分
             从位置标识开始从左到右:0,1,2,3,4,5...  */
            filename=QString(buf).section("##",0,0);
            fileSize=QString(buf).section("##",1,1).toInt();//QString->int


            //打开文件
            file.setFileName(filename);
            bool isok=file.open(QIODevice::WriteOnly);
            if(isok==false)
            {
                qDebug()<<"写入错误";
            }
        }
        else//发真正的文件数据
        {

                qint64 len=file.write(buf);//写入数据
                recvSize+=len;

                if(recvSize==fileSize)
                {
                    file.close();
                    QMessageBox::information(this,"ok","写入ok");
                    tcpSocket->disconnectFromHost();
                    tcpSocket->close();
                }
        }
    }
            );
//连接
void client::on_pushButtonlianjie_clicked()
{
    QString ip=ui->lineEditIP->text();
    qint16 port=ui->lineEditport->text().toInt();
    tcpSocket->connectToHost(QHostAddress(ip),port);

}

LINUX下的UDP

qt的UDP

    

qt的UDP单播举例:

只发送到另一个指定地址和端口的UDP客户端,是一对一的数据传输

.cpp

    udpSocket =new QUdpSocket(this);
    udpSocket->bind(8888);
    setWindowTitle("8888");//标题
    connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::dealMsg);//自定义槽函数

//接受对方的发来数据
    void Widget::dealMsg()
{
    char buf[1024]={0};
    QHostAddress cliAddr;
    quint16 port;
//对方连接“我”,“我”显示对方的ip,端口号和发来的数据
    qint64 len= udpSocket->readDatagram(buf,sizeof(buf),&cliAddr,&port);
    if(len>0)
    {
        QString str =QString("[%1:%2] %3").arg(cliAddr.toString()).arg(port).arg(buf);
        ui->textEdit->setText(str);
    }
}


//send控件
void Widget::on_Buttonsend_clicked()
{
    //使用UDP协议进行信息的传输之前不需要建立连接,只需要给出对方的ip地址和端口号
    QString ip =ui->lineEditip->text();
    qint16 port =ui->lineEditport->text().toInt();
    QString str =ui->textEdit->toPlainText();
    udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);
}

UDP的广播与组播(多播)

TCP只有点对点,UDP才有点对点、组播、广播的概念

使用UDP协议进行信息的传输之前不需要建立连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。 

对于广播,同一网络范围内其他所有的UDP客户端都可以收到。单播和广播的实现方式基本相同,只是数据报的目标IP地址设置不同,在广播消息时,只需要将目标地址更换为一个特殊地址,即广播地址QHostAddress::Broadcast,一般为255.255.255.255

对于组播,组内成员(组播IP地址指定的多播组)都可以接收到。使用组播地址,其他的端口绑定、数据报收发功能与单播UDP完全相同。

组播(一对一组):

当多个客户端加入由一个组播地址定义的多播组之后,客户端向组播地址和端口发送数据报,组内成员都可以接收到

224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其他地址供路由协议使用
224.0.1.0~224.0.1.255是公用组播地址,可以用于internet
224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效
239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效


 



这篇关于qt网络编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程