一、学到的东西:
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文件。