QT(傳視訊的雛形,連續傳圖片)
阿新 • • 發佈:2021-07-22
一、學到的東西:
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 APIin 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檔案。