C++ 服务器通过Tcp传输图片 到 QT客户端显示
简单的方法通过流数据传输图片,并且在QT上面显示出来这里贴出核心代码,供大家参考:
先附上资源源码:Qt客户端和C++服务器源码
客户端C++:
#include<iostream>
#include<winsock.h>
#include <fstream>
#include<string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization();
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
int len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
SOCKET s_accept;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
SOCKADDR_IN accept_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.2");
server_addr.sin_port = htons(1234);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_server, (SOCKADDR*)& server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "套接字绑定失败!" << endl;
WSACleanup();
}
else {
cout << "套接字绑定成功!" << endl;
}
//设置套接字为监听状态
if (listen(s_server, SOMAXCONN) < 0) {
cout << "设置监听状态失败!" << endl;
WSACleanup();
}
else {
cout << "设置监听状态成功!" << endl;
}
cout << "服务端正在监听连接,请稍候...." << endl;
//接受连接请求
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)& accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
cout << "连接失败!" << endl;
WSACleanup();
return 0;
}
cout << "连接建立,准备接受数据" << endl;
//接收数据
while (1) {
recv_len = recv(s_accept, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
else {
cout << "客户端信息:" << recv_buf << endl;
}
cout << "请输入回复信息:";
cin >> send_buf;
int a = 1;
char* buffer;
long size;
string FileDirect;
while (true)
{
a++;
if (a % 2 == 0) {
FileDirect = "D:\\test.jpg";//图像文件地址
}else
{
FileDirect = "D:\\test2.jpg";//图像文件地址
}
ifstream in(FileDirect, ios::in | ios::binary | ios::ate);
size = in.tellg();
in.seekg(0, ios::beg);
buffer = new char[size];
in.read(buffer, size);
in.close();
send_len = send(s_accept, buffer, size, 0);
delete[] buffer;
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
}
//关闭套接字
closesocket(s_server);
closesocket(s_accept);
//释放DLL资源
WSACleanup();
return 0;
}
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
主要代码分析:
while (true)
{
a++;
if (a % 2 == 0) {
FileDirect = "D:\\test.jpg";//图像文件地址
}else
{
FileDirect = "D:\\test2.jpg";//图像文件地址
}
ifstream in(FileDirect, ios::in | ios::binary | ios::ate);
size = in.tellg();
in.seekg(0, ios::beg);
buffer = new char[size];
in.read(buffer, size);
in.close();
send_len = send(s_accept, buffer, size, 0);
delete[] buffer;
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
这里我为了简单实现图片的连续传输,形成视频的效果,创建了一个循环,用来不断发送图片。
这里我在D盘放了两张图,这里的路径可以根据自己的需求更改。
下面是QT客户端的主要代码:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
tcpSocket = new QTcpSocket(this);
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(displayError(QAbstractSocket::SocketError)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
newConnect(); //请求连接
}
void MainWindow::newConnect()
{
blockSize = 0; //初始化其为0
tcpSocket->abort(); //取消已有的连接
//连接到主机,这里从界面获取主机地址和端口号
tcpSocket->connectToHost(ui->lineEdit->text(),
ui->lineEdit_2->text().toInt());
}
void MainWindow::readMessage()
{
QByteArray array = tcpSocket->readAll();
QImage bmpBuf;
bmpBuf.loadFromData(array);
ui->label_4->setPixmap(QPixmap::fromImage(bmpBuf));
}
void MainWindow::displayError(QAbstractSocket::SocketError)
{
qDebug() << tcpSocket->errorString(); //输出错误信息
}
void MainWindow::on_pushButton_2_clicked()
{
QByteArray block;
//使用数据流写入数据
QDataStream out(&block,QIODevice::WriteOnly);
//设置数据流的版本,客户端和服务器端使用的版本要相同
tcpSocket->write("hello Tcp!!!",100);
}
每次接收了之后把流文件转换成QImage并显示到UI上去。
UI布局如下:
头文件如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
#include <qfile.h>
#include <qfiledialog.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void newConnect(); //连接服务器
void readMessage(); //接收数据
void displayError(QAbstractSocket::SocketError); //显示错误
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
QTcpSocket *tcpSocket;
QString message;
quint16 blockSize;
};
#endif // MAINWINDOW_H
最后效果如图: