1. 程式人生 > 其它 >QT(傳視訊的雛形,連續傳圖片)

QT(傳視訊的雛形,連續傳圖片)

一、學到的東西:

1、gcc *.c可以同時編譯當前資料夾下的所有檔案

二、客戶端程式碼:

1、設計介面:

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檔案。