QT(传视频的雏形,连续传图片)

一、学到的东西:

1、gcc *.c可以同时编译当前文件夹下的所有文件

 

二、客户端代码:

1、设计界面:

QT(传视频的雏形,连续传图片)

2、.pro

QT       += core gui
QT += network
QT += core

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

 

3、widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QPixmap>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();
    void net_success();
    void pic_recv();


    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    QTcpSocket *socket;
    QTimer *tm;
    int piclen;
    char picbuf[500*1024];
};
#endif // WIDGET_H

 

4、widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    socket = NULL;
    tm = NULL;
    ui->label->setScaledContents(true);//自适应图片大小
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    if(NULL == socket)
    {
        //建立QTcpSocket类的对象
        socket = new QTcpSocket();
        //connectToHost函数就是将ip,端口号信息存入后和服务器创建连接,创建后socket将不再会是NULL。
        socket->connectToHost(ui->lineEdit->text(),ui->lineEdit_2->text().toInt());
        //建立QTimer类的对象
        tm = new QTimer();
    }
    //将信号函数connected与net_success()绑定,一但连接成功就执行net_success()函数
    connect(socket,SIGNAL(connected()),this,SLOT(net_success()));//connected()表示连接成功返回的信号
    connect(tm, SIGNAL(timeout()), this, SLOT(pic_recv()));
}

void Widget::net_success()
{
    ui->pushButton->setEnabled(false);//a按钮失效
}

void Widget::pic_recv()
{
    socket->write("pic",4);//向服务器发一条消息,表示需要传图片。
    char len[10] = {0};
    socket->read(len,10);
    piclen = atoi(len);
    socket->read(picbuf,piclen);//在读取的时候直到读取piclen长的内容后才进入下一步

    QPixmap pix;
    //loadFromData函数就是将图片的信息存入(内容,大小,后缀名)pix对象里面。
    pix.loadFromData((uchar *)picbuf,piclen,"jpg");
    //setPixmap函数就是将图片显示在label内。
    ui->label->setPixmap(pix);

}


void Widget::on_pushButton_2_clicked()
{
    tm->start(1000);//打开定时器1S触发一次而且一旦开启,需要主动去关闭不然一直计时
}

三、服务器代码:

1、main.c:

#include "ser.h"

int pic_send(int fd);

int main()
{
    int fd = tcp_server_init("0.0.0.0", 8888, 10);
    if(-1 == fd){
        perror("init");
        return -1;
    }

    int nfd = tcp_wait_connect(fd);
    if(-1 == nfd){
        perror("wait");
        return -1;
    }
    char cmd[4];
    while(1){
        read(nfd, cmd, 4);
        if(0 == strncmp(cmd, "pic", 3)){
            pic_send(nfd);        
        }else{
            return -1;
        }
    }
}

int pic_send(int fd)
{
    static int id = 1;
    if(4 == id){
        id = 1;
    }
    char name[10];
    sprintf(name, "%d.jpg", id);
    int rfd = open(name, O_RDONLY);
    if(-1 == rfd){
        return -1;
    }
    char buf[500*1024], pic_len[10];
    int piclen = 0, ret;
    while(1){
        ret = read(rfd, buf+piclen, 1024);
        if(0 == ret){
            break;
        }
        piclen += ret;
    }
    sprintf(pic_len,"%d", piclen);
    write(fd, pic_len, 10);
    write(fd, buf, piclen);
    id++;
}

2、ser.c

#include "ser.h"

//tcp server相关函数
int tcp_server_init(char *ip, int port, int backlog)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == fd){
        return -1;
    }

    struct sockaddr_in sddr;
    sddr.sin_family      = AF_INET;
    sddr.sin_port        = htons(port);
    sddr.sin_addr.s_addr = inet_addr(ip);
    if(-1 == bind(fd, (void *)&sddr, sizeof(sddr))){
        return -1;
    }

    if(-1 == listen(fd, backlog)){
        return -1;
    }
    puts("listen....");
    return fd;
}

int tcp_wait_connect(int fd)     
{
    struct sockaddr_in cddr;
    int len = sizeof(cddr);            
    int nfd = accept(fd, (void *)&cddr, &len);
    if(-1 == nfd){
        return -1;
    }
    printf("IP:%sPORT:%d connected!\n", inet_ntoa(cddr.sin_addr), ntohs(cddr.sin_port));
    return nfd;
}

3、ser.h

#ifndef _SER_H
#define _SER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//tcp server相关函数
int tcp_server_init(char *ip, int port, int backlog);
int tcp_wait_connect(int fd);
#endif

四、注意:

1、在服务器文件夹下需要有图片文件,当前代码为.jpg文件。

 

上一篇:Qt右键菜单


下一篇:Flutter | 一文搞懂 BuildContext