zoukankan      html  css  js  c++  java
  • QT TCPSocket和QTCPServer使用

    概述:QTcpSocket和QTcpServer可以实现TCP客户端和服务器端通信,本文介绍基于块的通信方式

    基于块的传输协议把数据作为二进制块进行传输。每一个块都由一个大小字段及其包含的数据域组成

    程序界面

     一个数服务端socket一个是客户端socket,客户端socket可以从服务器端socket下载文件

    运行过程

     客户端精度条显示文件下载进度。

    test.rar表示服务器要发送的文件,testreceived.rar表示客户端收到的文件

     因为测试服务器和客户端在同一目录下,所以该程序把收到的test.rar命名为testreceived.rar,以做区分

    核心代码

    connect(&tcpSocketClient,&QTcpSocket::connected,this,&FileTransferSocket::slotConnected);
    connect(&tcpSocketClient,&QTcpSocket::disconnected,this,&FileTransferSocket::slotDisconnected);
    connect(&tcpSocketClient,&QTcpSocket::readyRead,this,&FileTransferSocket::slotReadyRead);
    connect(&tcpSocketClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slotError(QAbstractSocket::SocketError)));

    slotReadyRead当对方socket有数据过来将会调用此槽函数

    1、tcpSocketClient.connectToHost("127.0.0.1",8888);

    连接到服务器端socket

    2、发送数据到连接的socket

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_1);
    out<<quint16(0)<<QString("downrequest");
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    tcpSocketClient.write(block);

    每次发送数据都是以块为单位的,上面代码发送一个块的数据

    但是需要注意的地方是,数据在网络传输中并不是以块为单位,也就是发送一整块数据,接收的socket可能不是一次正好接收一整个块

    可能收到一个完整的块或者一个块的一部分、一个块和另一个块的一部分、若干个块或者亦可能是所有的块,在接收端socket需要判断。

    先看看块的结构形式

    一个块包含两部分,一部分表示数据区域的大小,一部分表示数据区域

    out<<quint16(0)<<QString("downrequest");

    这段代码的quint16(0)用来存放数据区域的大小,QString("downrequest")表示数据区域

    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));

    这两行代码,分别是移到首位置,即数据数据区域大小

    然后给数据区域填充数据的实际大小值.

    3、我们来看看接收端socket如何接收数据

    在这里定义一个nextBlockSize变量

    用来存放每个块的大小。

    bytesAvailable()表示网络里面传过来的可用字节数,如果可用字节数已经大于或者等于sizeof(quint16)

    还记得quint16表示什么吗?这个区域存放的就是块的数据区域大小。

    如果可用字节数已经大于或者等于sizeof(quint16),这样我们就可以取出这个块的数据区域大小

    in >> nextBlockSize;

    然后再判断bytesAvailable()是否大于等于nextBlockSize如果不是说明这个块的数据还未完全传过来,等待网络数据传输(千万不要取已接收的数据,因为是不完整的)

    如果大于等于nextBlockSize,说明这一块的数据区域已经完全传过来了。

    //数据块完整可以接收
    QString clientrequest;
    in >> clientrequest;

    然后把数据区域的数据放到clientrequest里面。

    到此通过块的形式发送数据就完成了

    4、下面开始文件的传输

     先获取本地文件,打文件大小文件名称等信息传到客户端socket,当然上面代码是写死的文件名,你可以通过file直接获取文件名。

    上面的代码还未正式发送文件,只是把文件的一些信息发送给客户端socket。

    5、

    connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(slotBytesWritten(qint64)));

    bytesWritten(qint64))这个信号每次数据写入设备后会激发

    在此槽函数里面读取文件并发送文件到客户端

    文件分多次发送,每当有数据写入的设备改槽函数都执行,直到文件发送完毕

    6.我们再看看文件接收端

     这里就不做详细讲解了,主要就是从sokcet读取说有数据,然后文件写入

  • 相关阅读:
    网易云服务器使用https
    网站搬家后firefox,chrome提示内容编码错误,360浏览器提示500错误
    腾讯云centos服务器配置
    微擎二次开发相关
    mysql 分组查询最新的/最高的一条记录
    .htaccess ci放在子目录时规则
    小程序 html解析
    源于一道文字游戏的题目
    C# 获取系统时间及时间格式
    操作bin目录下的文件
  • 原文地址:https://www.cnblogs.com/tianmochou/p/12851663.html
Copyright © 2011-2022 走看看