{C++系列} Qt day06 QT多线程,线程同步,生产者消费者,Qt网络编程
in C/C++ with 0 comment

{C++系列} Qt day06 QT多线程,线程同步,生产者消费者,Qt网络编程

in C/C++ with 0 comment

回顾:
1 常用SQL语句
CREATE TABLE 表名(列名 类型 [约束],...);
DROP TABLE 表名;
INSERT INTO 表名 (列名,...) VALUES(数值,...)
DELETE FROM 表名 WHERE 条件;
UPDATE 表名 SET 列名=数值,... WHERE 条件;
SELECT 列名,... FROM 表名

            WHERE 条件  ORDER BY 列名 ASC/DESC;

2 QT中使用Sqlite
1)QSqlDatabase
2)QSqlQuery
3)QSqlQueryModel

=============================
今天:
一 QT多线程QThread
1 创建线程方法1:QObject::moveToThread
class Worker:public QObject
{

void doWork(const QString &parameter){
    /*耗时或阻塞操作*/
}

};
class Controller:public QObject
{

 //线程对象
QThread workerThread;

public:

Controller() {
      //创建Workker对象
    Worker *worker = new Worker;
    //将work对象移动到线程对象中
    worker->moveToThread(&workerThread);
    //开启线程,将来通过worker调用doWork将会在一个独立的线程中执行
    workerThread.start();
}

};
2 创建线程方法2:继承QTread,重写run函数//推荐
class WorkerThread : public QThread
{

Q_OBJECT
//线程入口函数(虚函数)
void run(void){
    /*耗时或阻塞操作*/       
}

};

//创建线程对象
WorkerThread *workerThread
            = new WorkerThread(this);   

//开启线程,run函数将在一个独立线程中被执行
workerThread->start();

3 相关函数
1)线程等待//类似pthread_join
bool QThread::wait()
2)线程退出//类似pthread_exit
void exit()
void quit()[slot]
3)开始线程//类似pthread_create
void start();
注:线程函数run将被执行
4)线程终止//类似pthread_cancel
void terminate()

//设置一个线程是否允许被终止
QThread::setTerminationEnabled(bool)
eg:
void run(void){

setTerminationEnabled(false);//不允许被终止
//执行关键操作
setTerminationEnabled(true);//恢复

}
5)获取线程句柄(ID)
Qt::HANDLE currentThreadId()

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

二 线程同步
1 互斥锁(互斥量) QMutex

int num = 0;
QMutex mutex;

线程1:
void run(){

      for(int i=0;i<100;i++){
          mutex.lock();
          int tmp = num;
          tmp = tmp+1;
          num = tmp;
          mutex.unlock();
      }

}
线程2:
void run(){

      for(int i=0;i<100;i++){
          mutex.lock();
          int tmp = num;
          tmp = tmp+1;
          num = tmp;
          mutex.unlock();
      }

}

2 读写锁 QReadWriteLock
eg:
QReadWriteLock lock;
void ReaderThread::run()//读文件线程
{

...
lock.lockForRead();
read_file();
lock.unlock();
...

}
void WriterThread::run()//写文件线程
{

...
lock.lockForWrite();
write_file();
lock.unlock();
...

}

3 信号量 QSemaphore
PV操作:
P操作:申请资源,对信号量-1操作
V操作:释放资源,对信号量+1操作

《案例》生产者和消费者
问题:
1)生产者向仓库中存放数据,但是如果生产的太快,那么将会把消费者还未来得及读取的数据覆盖掉。
2)消费者从仓库中获取数据,但是如果消费的太快,
那么它会越过生产者获取到垃圾数据。
解决:使用两个信号量
一个信号量控制生产者线程,如果缓冲区满则阻塞
另一个信号量控制消费者线程,如果缓冲区空则阻塞

4 条件变量 QWaitCondition

=====================
三 QT网络编程
//回顾UC网络编程
1 网络协议层次(OSI七层/linux四层)
应用层 http、ftp、SMTP、tftp、DNS...
表示层
会话层
传输层 TCP/UDP
网络层 IPv4/IPv6
数据链路层
物理层

2 socket编程C/S
1)TCP服务器
--》创建套接字:socket()
--》准备服务器地址:struct sockaddr_in
--》绑定:bind()
--》监听:listen()
--》等待客户端的连接:accept()
注:accept返回一个新的套接字用于和客户端通信
--》创建子进程或子线程,处理和客户端通信
--》和客户端进行通信

write()/read();
send()/recv();

--》close()

2)TCP客户端
--》创建和服务器通信套接字:socket()
--》准备服务器地址:struct sockaddr_in
--》向服务器发送连接请求:connect()
--》和服务器进行通信

write()/read();
send()/recv();

--》close()

===================
1)UDP服务器
--》创建套接字:socket()
--》准备服务器地址:struct sockaddr_in
--》绑定:bind()
--》和客户端进行通信
sendto()/recvfrom()
--》close()

2)UDP客户端
--》创建和服务器通信套接字:socket()
--》准备服务器地址:struct sockaddr_in
--》和服务器进行通信

sendto()
recvfrom()/read()

--》close()

3 QT中和socket编程相关类

include <QHostAddress> //网络地址

include <QAbstactSocket> //套接字基类

include <QTcpSocket>

include <QTcpServer>

include <QUdpSocket>

Responses