--------------------------------------------------------------------------------------------------------
最终效果图:
--------------------------------------------------------------------------------------------------------
注意:图片发送大体流程同《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();
}
最终效果图:
--------------------------------------------------------------------------------------------------------
注意:此处只有服务端采用了多线程,即可以接收多个客户端的访问并进行相互
通信。这里在使用时必须先启动服务端再启动客户端,此时在服务端的左侧方框
内会显示与服务端连接的客户端名。鼠标点击你想要通信的客户名然后在发送消
息即可。
--------------------------------------------------------------------------------------------------------
服务端:
GUI界面设计:
--------------------------------------------------------------------------------------------------------
实现代码:
非线程部分:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include<QMainWindow> #include<QtNetwork/QTcpServer> #include<QStandardItemModel> #include"socketthread.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); QStandardItemModel *model; protected: void init(); void newListen(); private: Ui::MainWindow *ui; QTcpServer *tcpServer; signals: void sendToSocketThrd(QString client,QString datas); private slots: void createSocketThread(); void revFromThrd(bool isClient,QString datas); void removeClient(QString client); //void addSocketDescription(int socketdescription); //void removeSocketDescription(int socketdescription); void on_send_clicked(); void on_friendlist_clicked(QModelIndex index); }; #endif // MAINWINDOW_H
///
#include "mainwindow.h" #include "ui_mainwindow.h" int Des[256] = {0}; int clientNum = 0; QString currentClient; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); init(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::init() { tcpServer = new QTcpServer; model = new QStandardItemModel(); model->setColumnCount(2); model->setHeaderData(0,Qt::Horizontal,"NAME"); model->setHeaderData(1,Qt::Horizontal,"IP"); connect(tcpServer,SIGNAL(newConnection()),this,SLOT(createSocketThread())); ui->friendlist->setModel(m odel); ui->friendlist->hideColumn(1); ui->friendlist->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); ui->friendlist->setEditTriggers(QAbstractItemView::NoEditTriggers); newListen(); } void MainWindow::newListen() { if(!tcpServer->listen(QHostAddress::Any,6666)) { qDebug()<<tcpServer->errorString(); tcpServer->close(); return ; } } void MainWindow::createSocketThread() { socketThread *SThread = new socketThread(tcpServer->nextPendingConnection()); connect(SThread,SIGNAL(sendToMainWin(bool,QString)),this,SLOT(revFromThrd(bool,QString))); connect(SThread,SIGNAL(closeClient(QString)),this,SLOT(removeClient(QString))); //connect(SThread,SIGNAL(sendSocketDescription(int)),this,SLOT(addSocketDescription(int))); //connect(SThread,SIGNAL(closeSocketDescription(int)),this,SLOT(removeSocketDescription(int))); connect(this,SIGNAL(sendToSocketThrd(QString,QString)),SThread,SLOT(revFromMainWin(QString,QString))); SThread->start(); } void MainWindow::on_send_clicked() { QString message; message = "SERVER\n"+ui->message->document()->toPlainText(); ui->message->clear(); emit sendToSocketThrd(currentClient,message); } /* void MainWindow::addSocketDescription(int socketdescription) { for(int i = 0; i < 256; i++) { if(Des[i] == 0) { Des[i] = socketdescription; break; } } } void MainWindow::removeSocketDescription(int socketdescription) { for(int i = 0; i < 256; i++) { if(Des[i] == socketdescription) { Des[i] = 0; break; } } } */ void MainWindow::revFromThrd(bool isClient,QString datas) { if(isClient) { QString tmp; tmp = QString(strtok(datas.toLatin1().data(),"\n")); model->setItem(clientNum,0,new QStandardItem(tmp)); tmp = QString(strstr(datas.toLatin1().data(),"\n")).mid(1); model->setItem(clientNum,1,new QStandardItem(tmp)); clientNum++; } else { ui->displaymessage->append(datas); } } void MainWindow::removeClient(QString client) { for(int i = 0; i < clientNum;i++) { if(model->item(i)->text().operator ==(client)) { model->removeRow(i); clientNum--; break; } } } void MainWindow::on_friendlist_clicked(QModelIndex index) { currentClient = index.data().toString()+"\n"; currentClient += index.sibling(index.row(),1).data().toString(); }
///
线程部分:
#ifndef SOCKETTHREAD_H #define SOCKETTHREAD_H #include<QThread> #include<QtNetwork/QTcpSocket> #include<QtNetwork/QHostAddress> class socketThread : public QThread { Q_OBJECT public: explicit socketThread(QObject *parent = 0); socketThread(QTcpSocket *socket); QString ip; QString clientName; bool isClient; int description; protected: void run(); signals: void sendToMainWin(bool isClient,QString datas); void sendSocketDescription(int socketDescription); void closeClient(QString client); private slots: void revFromMainWin(QString client,QString datas); void closeSocket(); void revDatas(); private: QTcpSocket * tcpSocket; }; #endif // SOCKETTHREAD_H
///
#include "socketthread.h" socketThread::socketThread(QObject *parent) : QThread(parent) { } socketThread::socketThread(QTcpSocket *socket) { tcpSocket = socket; isClient = true; description = tcpSocket->socketDescriptor(); ip = tcpSocket->peerAddress().toString(); connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revDatas())); } void socketThread::run() { connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(closeSocket())); } void socketThread::revDatas() { if(isClient) { clientName = tcpSocket->readAll(); emit sendToMainWin(isClient,clientName+"\n"+ip); isClient = false; } else { emit sendToMainWin(isClient,clientName+"\n"+tcpSocket->readAll()); } } void socketThread::revFromMainWin(QString client,QString datas) { QString tmp = clientName+"\n"+ip; if(tmp.operator ==(client)) { tcpSocket->write(datas.toLatin1().data()); } } void socketThread::closeSocket() { emit closeClient(clientName); tcpSocket->close(); }
--------------------------------------------------------------------------------------------------------
服务端:
GUI界面设计:
--------------------------------------------------------------------------------------------------------
实现代码:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include<QtNetwork> #include<QtNetwork/QTcpSocket> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); QString myName; protected: void init(); void newTCPConnect(); private: Ui::MainWindow *ui; QTcpSocket *tcpSocket; private slots: void revData(); void sendMyName(); void displayError(QAbstractSocket::SocketError); void on_send_clicked(); }; #endif // MAINWINDOW_H
///
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include<QtNetwork> #include<QtNetwork/QTcpSocket> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); QString myName; protected: void init(); void newTCPConnect(); private: Ui::MainWindow *ui; QTcpSocket *tcpSocket; private slots: void revData(); void sendMyName(); void displayError(QAbstractSocket::SocketError); void on_send_clicked(); }; #endif // MAINWINDOW_H