day_06_多线程、网络编程

来源:互联网 发布:表单设计软件 mac 编辑:程序博客网 时间:2024/05/22 09:50

    • 十三QT多线程QThread
      • 1创建线程方法1moveToThread
      • 2创建线程方法2继承QThread重写run函数推荐
      • 3退出线程
      • 4等待线程
      • 5开启线程
      • 6终止线程
      • 7获取当前线程的句柄ID
      • 8线程同步
        • 1互斥锁 QMutex
        • 2读写锁 QReadWriteLock
        • 3信号量 QSemaphore
        • 4条件变量 QWaitCondition
    • 十四QT网络编程
      • 1网络的协议层次OSI七层
      • 2回顾linux的socket编程
        • 1TCP编程
        • 2UDP编程

十三、QT多线程(QThread)

1、创建线程方法1:moveToThread

class Worker:public QObject{    QOBJECTpublic slot:    void doWork(const QString &parameter){        QString result;        /* ..耗时或阻塞的操作.. */        emit resultReady(result);    }signals:    void resultReady(const QString &result);};class Controller:public QObject{    QOBJECT    // 创建线程对象    QThread workerThread;public:    Controller() {        Worker *worker = new Worker;        // Worker对象移动到线程中        worker->moveToThread(&workerThread);        // 当发送operate信号,dowork将在一个独立的线程中执行        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);        connect(this, &Controller::operate, worker, &Worker::doWork);        connect(worker, &Worker::resultReady, this, &Controller::handleResults);        // 开启        workerThread.start();    }    ~Controller() {        workerThread.quit();        workerThread.wait();    }public slots:    void handleResults(const QString &);signals:    void operate(const QString &);};

2、创建线程方法2:继承QThread,重写run函数(推荐)

class WorkerThread : public QThread{    Q_OBJECT    // 线程的入口函数    void run() Q_DECL_OVERRIDE {        QString result;        /* 耗时或阻塞的操作 */        emit resultReady(result);    }signals:    void resultReady(const QString &s);};void MyObject::startWorkInAThread(){    // 创建线程对象    WorkerThread *workerThread = new WorkerThread(this);    connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);    connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);    // 开启线程    workerThread->start();}

3、退出线程

void QThread::exit(int returnCode = 0)void QThread::quit() [slot]

4、等待线程

bool QThread::wait(unsigned long time = ULONG_MAX)

5、开启线程

void QThread::start(Priority priority = InheritPriority)

6、终止线程

void QThread::terminate()// 设置线程是否允许被终止(默认:true,设置为false后线程不能被terminate()终止)void QThread::setTerminationEnabled(bool enabled = true)

7、获取当前线程的句柄(ID)

Qt::HANDLE QThread::currentThreadId()

案例:多线程打印消息
工程名:Thread
类名:ThreadDialog

8、线程同步

1)互斥锁 QMutex

QMutex mutex;mutex.lock();    // 加锁mutex.unlock();  // 解锁

2)读写锁 QReadWriteLock

void QReadWriteLock::lockForRead();  // 加读锁void QReadWriteLock::lockForWrite(); // 加写锁

3)信号量 QSemaphore

QSemaphore::QSemaphore(int n = 0);  // 初始化资源个数为nvoid QSemaphore::acquire(int n = 1);// 获取一个资源(p:信号量-1)void QSemaphore::release(int n = 1);// 释放一个资源(v:信号量+1)

案例:生产者和消费者
问题:
  1)生产者向仓库存放数据,但是如果生产的太快,将会把消费者还未读走的数据覆盖;
  2)消费者从仓库中获取数据,但是如果消费者消费的太快,将会越过生产者,读走一些无效数据;
解决方法:
  使用两个信号量,一个信号量(freeSpace)控制生产者,如果仓库满则等待;另一个信号量(usedSpace)控制消费者,如果仓库空则等待;

/* 生产者线程 */while(1){    p(freeSpace)    // 生产一个产品并存放到仓库    v(usedSpace)}/* 消费者线程 */while(1){    p(usedSpace)    // 从仓库中取出一个产品    v(freeSpace)}

4)条件变量 QWaitCondition

QWaitCondition w;  // 创建条件变量w.wait(&mutex);    // 让当前线程进入休眠,同时解锁w.wakeAll();       // 唤醒所有等待的线程w.wakeOne();       // 唤醒一个等待的线程

十四、QT网络编程

1、网络的协议层次(OSI七层)

层次 协议 应用层 HTTP、FTP、SMTP、POP3、DNS.. 表示层 会话层 传输层 TCP、UDP 网络层 IPv4、IPv6 数据链路层 以太网 物理层

扩展:

协议 全称 HTTP 超文本传输协议(Hyper Text Transfer Protocol) FTP 文件传输协议(File Transfer Protocol) SMTP 简单邮件传输协议(Simple Mail Transfer Protocol) POP3 邮局协议版本3(Post Office Protocol - Version 3) DNS 域名系统(Domain Name System) TCP 传输控制协议(Transmission Control Protocol ) UDP 用户数据报协议(User Datagram Protocol)

2、回顾linux的socket编程

1)TCP编程

服务器:
  a. 创建socket套接字:socket()
  b. 准备服务器地址:struct sockaddr_in
  c. 绑定bind()
  d. 监听listen(sfd, 100)
  e. 等待客户端的连接accept()(开启子进程或子线程)
  f. 通信:read()/write()recv()/send()
  g. 关闭close()
客户端:
  a. 创建socket套接字:socket()
  b. 准备服务器地址:struct sockaddr_in
  c. 向服务器发送连接请求:connect()
  d. 通信:read()/write()recv()/send()
   f. 关闭close()

2)UDP编程

服务器端:
  a. 创建socket套接字socket()
  b. 准备服务器地址struct sockaddr_in
  c. 绑定bind()
  d. 通信:recvfrom()/sendto()
  e. 关闭

客户端:
  a. 创建socket套接字:socket()
  b. 准备服务器地址:struct sockaddr_in
  c. 通信:read()/recvfrom()/sendto()
  e. 关闭close()