Qt網路程式設計—TCP/IP(二)
軟體環境: ubuntu
--------------------------------------------------------------------------------------------------------
最終效果圖:
--------------------------------------------------------------------------------------------------------
注意:圖片傳送大體流程同《Qt網路程式設計—TCP/IP(一)》只是在傳送時這裡採用
的資料流QDataStream形式。因為使用攝像進行監控時也是對一幀一幀的圖片進
行處理,因此掌握瞭如何用Qt網路實現圖片傳輸基本就可以實現遠端實時監控。
--------------------------------------------------------------------------------------------------------
服務端:
GUI介面設計:
--------------------------------------------------------------------------------------------------------
實現程式碼:
#include<QtNetwork>
#include<QtNetwork/QTcpServer>
#include<QtNetwork/QTcpSocket>
#include<QImage>
#include<QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QImage *image;
QTimer *timer;
protected:
void init();
void displayvideo();
private:
Ui::MainWindow *ui;
QTcpSocket *tcpSocket;
QTcpServer *tcpServer;
private slots:
void newListen();
void acceptConnection();
void displayError(QAbstractSocket::SocketError);
void on_send_clicked();
void sendData();
};
#endif // MAINWINDOW_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "ui_mainwindow.h"
int count = 1;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
this->tcpServer = new QTcpServer(this);
this->tcpSocket = new QTcpSocket(this);
timer = new QTimer;
newListen();
connect(timer,SIGNAL(timeout()),this,SLOT(sendData()));
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(displayError(QAbstractSocket::SocketError)));
}
void MainWindow::newListen()
{
if(!tcpServer->listen(QHostAddress::Any,6666))
{
qDebug()<<tcpServer->errorString();
close();
return;
}
}
void MainWindow::acceptConnection()
{
tcpSocket = tcpServer->nextPendingConnection();
}
void MainWindow::displayError(QAbstractSocket::SocketError)
{
qDebug()<<tcpSocket->errorString();
tcpSocket->close();
}
void MainWindow::on_send_clicked()
{
timer->start(300);
//sendData();
}
void MainWindow::sendData()
{
//timer->stop();
QByteArray Data;
QBuffer buffer;
QDataStream out(&Data,QIODevice::WriteOnly);
displayvideo();
image->save(&buffer,"jpg");
//這裡在傳送一張圖片時必須先將圖片大小資訊寫入待發送資料流中在將JPG格式圖片寫入資料流這樣可以
//確保客 戶端能正確接收一張完整圖片。
out.setVersion(QDataStream::Qt_4_6);
out<<(quint32)buffer.data().size();
Data.append(buffer.data());
tcpSocket->write(Data);
delete image;
Data.resize(0);
buffer.reset();
// timer->start(100);
}
void MainWindow::displayvideo()
{
FILE *fp;
char file[105776] = {0};
char name[10] = {0};
sprintf(name,"tu/%d.jpg",count++);
fp = fopen(name,"rb");
fread(&file,105776,1,fp);
fclose(fp);
if(count == 11) count = 1;
image = new QImage((unsigned char*)file,0,0,QImage::Format_RGB16);
image->loadFromData((unsigned char*)file,105776);
ui->label->setScaledContents(true);
ui->label->setPixmap(QPixmap::fromImage(*image,Qt::AutoColor));
}
--------------------------------------------------------------------------------------------------------
客服端:
GUI介面設計:
--------------------------------------------------------------------------------------------------------
實現程式碼:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include<QMainWindow>
#include<QtNetwork>
#include<QtNetwork/QTcpSocket>
#include<QImage>
#include<QImageReader>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int datasize;
protected:
void init();
void newTCPConnect();
void displayvideo();
private:
Ui::MainWindow *ui;
QTcpSocket *tcpSocket;
private slots:
void revData();
void displayError(QAbstractSocket::SocketError);
};
#endif // MAINWINDOW_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
tcpSocket = new QTcpSocket(this);
datasize = 0;
newTCPConnect();
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revData()));
connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(displayError(QAbstractSocket::SocketError)));
}
void MainWindow::newTCPConnect()
{
tcpSocket->abort();
tcpSocket->connectToHost(QHostAddress::Any,6666);
}
void MainWindow::revData()
{
//客服端第一次先接收資料流中圖片大小資訊
if(datasize == 0)
{
QDataStream in(tcpSocket);
in.setVersion( QDataStream::Qt_4_6);
if(tcpSocket->bytesAvailable() < sizeof(quint32))
{
return;
}
in>>datasize;
}
//然後根據圖片大小資訊接收JPG格式圖片
if(datasize > tcpSocket->bytesAvailable())
{
return;
}
//顯示接收到的圖片
displayvideo();
}
void MainWindow::displayvideo()
{
QByteArray Data = tcpSocket->read(datasize);
QBuffer buffer(&Data);
buffer.open( QIODevice::ReadOnly);
QImageReader reader(&buffer, "jpg");
QImage image = reader.read();
ui->label->setScaledContents(true);
ui->label->setPixmap(QPixmap::fromImage(image,Qt::AutoColor));
if(datasize != 0) ui->label_2->setText(QString::number(datasize));
//將datasize圖片大小資訊重置0為下一接收做準備。
datasize = 0;
}
void MainWindow::displayError(QAbstractSocket::SocketError)
{
qDebug()<<tcpSocket->errorString();
tcpSocket->close();
}