1.首先需要知道的知识
1.我使用的是 TCP 协议传输 ,因为传输数据准确一点,
2. 然后是 套接字的 信号 , readyRead( ) ,这个信号的功能是只要套接字里面的 缓存区有数据,他就会发出这个信号。
3.我们传输数据有时候,会出现 粘包和封包的情况,可能读取函数不能一次性的把数据读取。
4.所以我们传输数据的时候需要, 传输 一个 标志位, 一个数据的大小, 数据,三个数据。
标志位的作用: 标志新的数据从这里开始传输,
数据大小的作用: 可以明确的说明我们这次传输的图片数据的大小
数据: 图片的数据,转化为二进制。
5.发送一个图片需要 发送三次数据, 就是 利用套接字 的write 函数。(使用 write 三次)
2.代码解释,
发送模块:
QBuffer 类型
QBuffer为Qtl里面的缓冲区类
缓冲区的本质就是一段连续的存储空间
QImage 类型的 保存函数, 他把 image 图片的数据保存在 buff 里面
接收模块:
1.首先 我们接收函数包括这一部分,然后 因为readRead() 信号,可以在数据读取完之前,无限的调用,
2.type 是标志位
3.size 是数据的大小,
4. data 是总的数据大小的汇集,最后形成一张图片的数据。
3.所有的代码:
服务器: pro文件 + 网络的模块
ui 设计界面:
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QMainWindow>
/******* 摄像头相关类 *****/
#include <QCamera> /*** 摄像头类 ***/
#include <QCameraInfo> /*** 系统摄像头属性类 ***/
#include <QCameraImageCapture> /*** 用于记录摄像头数据的类 ***/
#include <QDebug> /*** debug 调试类 ****/
/******* 网络相关类 ****/
#include <QNetworkAccessManager> /** 网络访问类 ***/
#include <QNetworkReply> /** 网络数据结果类 ***/
/******* QJSON 相关类 *****/
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QTcpServer> /** TCP 服务器类 ***/
#include <QTcpSocket> /** TCP 套接字类 ***/
#include <QTimer> //定时器
#include <QTime>//时间类
#include <QFile>//文件类
#include <QFileDialog>
#include <QFileInfo>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_open_clicked();
void on_pushButton_close_clicked();
private:
Ui::Widget *ui;
QCamera *m_Camera; /*** 摄像机类对象 ***/
QCameraImageCapture *CameraImageCapture; /*** 用于记录摄像头数据的类 ***/
QNetworkAccessManager *m_http; /**网络访问对象 **/
QTcpServer *sevser;//服务器的套接字的网络对象
QTimer* timer;//定时器
QTcpSocket * mycli;//连接的对象
public slots:
void solt_newConnection();
void slot_pushButton_play();//拍照按键
void slot_CameraImageCapture(int id, QImage image);//照片在界面上显示的函数
void slot_TcpSocket_disconnected();//TCP 断开连接
signals:
void send();
};
#endif // WIDGET_H
.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <QBuffer>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);//定时器
sevser = new QTcpServer(this);
sevser->listen(QHostAddress::Any,10001);//监听开始
connect(sevser,SIGNAL(newConnection()),this,SLOT(solt_newConnection()));//建立信号连接 ,与链接的人
connect(ui->pushButton_play,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_play()));
//按键的初始化
ui->pushButton_close->setEnabled(false);//开始的时候 关闭摄像头的按钮不使能
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_open_clicked()//打开摄像头
{
ui->pushButton_open->setEnabled(false);//打开摄像头的按钮 不使能
ui->pushButton_close->setEnabled(true);//关闭摄像头的按钮 使能
/**** 摄像头初始化 ****/
QCameraInfo camreinfo = QCameraInfo::defaultCamera(); /*** 获取系统默认摄像头 ***/
if(camreinfo.isNull() == true)
{
QMessageBox::warning(this,"警告","系统没有可用摄像头");
return ;
}
/**** 申请摄像头类空间 ****/
m_Camera = new QCamera(camreinfo); // 直接使用系统默认的
m_Camera->setCaptureMode(QCamera::CaptureStillImage); //设置捕捉模式为静态帧(图片形式)
m_Camera->setCaptureMode(QCamera::CaptureMode::CaptureViewfinder); //将采集到取景器中
m_Camera->setViewfinder(ui->widget); //将摄像头数据输出到 UI 界面显示
m_Camera->start(); //摄像头打开
/***** 将摄像头放入摄像头记录类中,方便拍照 ******/
CameraImageCapture = new QCameraImageCapture(m_Camera);
CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
/*********** 捕获信号函数 imageCaptured(int,QImage) 拍了一张照,发出该信号 ********/
connect(CameraImageCapture,SIGNAL(imageCaptured(int,QImage)),this,SLOT(slot_CameraImageCapture(int,QImage)));
}
void Widget::on_pushButton_close_clicked()//关闭摄像头
{
ui->pushButton_close->setEnabled(false);//关闭摄像头的按钮 不使能
ui->pushButton_open->setEnabled(true);//开启摄像头的按钮使能
delete m_Camera; //释放他的空间
delete CameraImageCapture; //释放他的空间
}
void Widget::solt_newConnection()//连接成功之后的调试
{
qDebug()<<"连接成功";
mycli=new QTcpSocket(this);
mycli= sevser->nextPendingConnection(); //去读已连接客户端挂起的第一个
connect(mycli,SIGNAL(disconnected()),this,SLOT(slot_TcpSocket_disconnected()));
QHostAddress hostaddr = mycli->peerAddress(); /** 获取主机信息 **/
QString ip = hostaddr.toString();
int port = mycli->peerPort();
QString PORT = QString::number(port);
ui->listWidget->addItem(ip + " - " + PORT);//同步插入
connect(timer,SIGNAL(timeout()),this,SLOT(slot_pushButton_play()));
timer->start(30);
}
void Widget::slot_CameraImageCapture(int id, QImage image)
{
ui->label_3->setPixmap(QPixmap::fromImage(image));
bool ok = ui->checkBox->isChecked();
if(ok==true)
{
QByteArray data;
QBuffer buff(&data);
image.save(&buff,"jpeg");
u8 type = 0xAA; //接收到0xAA,我的长度来了
size_t size = data.size();
mycli->write((char *)&type,sizeof(type)); //发送类型
mycli->write((char *)&size,sizeof(size)); //发送长度
mycli->write(data); //发送数据
}
}
void Widget::slot_TcpSocket_disconnected()
{
qDebug()<<"TCP连接已经断开";
}
void Widget::slot_pushButton_play()
{
qDebug()<<"照片存入成功";
CameraImageCapture->capture("D:/QT/hqyj_coding/day07_video_transmission/gwww.jpg");
}
客户端
ui 设计界面 ,
头文件,
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
QTcpSocket *TcpSocket;
public slots:
void slot_TcpSocket_readyRead();
};
#endif // WIDGET_H
.cpp 文件 (地址自己写)
#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
TcpSocket = new QTcpSocket(this);
TcpSocket->connectToHost(QHostAddress("192.168.111.206"),10001);
connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(slot_TcpSocket_readyRead()));
}
Widget::~Widget()
{
delete ui;
}
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
void Widget::slot_TcpSocket_readyRead()
{
static u8 type = 0; //接收到0xAA,我的长度来了
static size_t size = 0;
static QByteArray data;
if(size == 0)
{
TcpSocket->read((char *)&type,sizeof(type)); //读取类型
if(type == 0xAA)
{
TcpSocket->read((char *)&size,sizeof(size)); //读取类型
data.clear();
type = 0;
}
}
if(size > 0)
{
QByteArray buf = TcpSocket->read(size); //读取类型
data.append(buf);
size -= buf.size();
if(size <= 0)
{
QImage image = QImage::fromData(data);
ui->label->setPixmap(QPixmap::fromImage(image));
}
}
}
最后结果