一秋忙,前言
因?yàn)樽穭。孕菹⒘硕螘r(shí)間铭若,同時(shí)也思考了下我的小項(xiàng)目接著會(huì)像哪個(gè)方向走。現(xiàn)在我基本定義了之后要做的QT項(xiàng)目功能了递览,能想象出一個(gè)雛形叼屠,且知道應(yīng)該先添加什么功能再添加什么功能。但是我還是處于小功能的練手階段绞铃。
二镜雨,需求
- client實(shí)現(xiàn)socket時(shí)時(shí)通信線程和2ms task線程。
- server端也一樣儿捧。
- 為了文件夾架構(gòu)漂亮冷离,便于移植。需要將獨(dú)立的功能模塊設(shè)計(jì)為pri子工程纯命。
三,遇到的問題
1. pri子工程和我之前多工程有什么區(qū)別痹栖?
答:37.QT多工程項(xiàng)目建立方法--Apple的學(xué)習(xí)筆記亿汞,里面描述的等于主工程調(diào)用子工程的dll,子工程是可以獨(dú)立編譯的揪阿,文件夾內(nèi)是pro疗我。而pri子工程無法獨(dú)立編譯咆畏,其實(shí)是文件夾的意思。pro中添加include (./udsServer/udsServer.pri)
吴裤。pri文件的添加就是一個(gè)txt文件修改后綴名后將文件導(dǎo)入pro工程旧找。或者說重新打開pro工程即可識(shí)別麦牺。
2. 線程如何安全的退出钮蛛?
答:一種方法是主線程調(diào)用線程對(duì)象的wait函數(shù),然后線程內(nèi)部調(diào)用自己quit剖膳。另外一種方法是在主線程中創(chuàng)建線程魏颓,然后將類moveToThread。主線程銷毀它也跟著銷毀了吱晒。
3. plantText如何顯示大寫甸饱?
答:str.toUpper。ui->textEdit->append(MsgInfo.toUpper());
仑濒。
4. 為Qlist的數(shù)組賦值跑飛叹话?
答:不能直接data[0]=1,而要data.append(1)墩瞳。因?yàn)樗鼪]有分配空間驼壶。
5. 線程中添加while(1)后會(huì)阻塞信號(hào)觸發(fā)
答:網(wǎng)上搜索了下QT信號(hào)連接有5種方式,其中直接連接可以不被阻塞矗烛,但是不安全辅柴。需要添加QCoreApplication::processEvents();
這樣可以專門來處理信號(hào),但是我while(1)中有msleep所以信號(hào)處理不是時(shí)時(shí)的瞭吃,由于我是2ms發(fā)一幀碌嘀,所以可以用這樣的方法。其實(shí)我目的是仿真ECU的2ms_task歪架。其實(shí)也可以用timer的timeout股冗,只是我想使用下事件循環(huán)的設(shè)計(jì),通過while循環(huán)掃描各種事件后處理的思路和蚪。
void udsServer::run()
{
initTask();
while (m_taskRunning) {
//Sleep(2);
QThread::msleep(2);
Task_2ms();
if(m_bSendevent==TRUE)
{
emit sendResponseFrame_sig(sendFrame);
m_bSendevent = FALSE;
}
QCoreApplication::processEvents();
}
m_pThread->quit();
}
6. c++如何和c函數(shù)交互
答:函數(shù)打包到extern "C" { xx函數(shù)}
即可止状。然后c就可以調(diào)用c++,c++也可以調(diào)用c攒霹。然后被c函數(shù)調(diào)用的函數(shù)中傳遞全局變量比較簡(jiǎn)單怯疤,我當(dāng)前是這樣設(shè)計(jì)的。當(dāng)然也可以傳遞全局定義的c++對(duì)象催束,然后調(diào)用此c++對(duì)象的方法集峦。應(yīng)該還能使用c++的靜態(tài)方法,之后可以嘗試下。
#ifdef __cplusplus
extern "C" {
#endif
extern xxC語言中的函數(shù)
#ifdef __cplusplus
}
extern "C" {
bool c++中的函數(shù)
}
7. 關(guān)于int轉(zhuǎn)16進(jìn)行且補(bǔ)0的方法?
答:QString("%1").arg(msg.CANData[1], 2, 16, QChar('0'))
其中2就是填充2個(gè)字節(jié)塔淤,填充的內(nèi)容就是0摘昌,至于轉(zhuǎn)16進(jìn)制就是里面的16。
void Widget::showTxMsg(CANMsg &msg)
{
QString MsgData = QString("%1").arg(msg.CANData[0], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[1], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[2], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[3], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[4], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[5], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[6], 2, 16, QChar('0'))+" "+
QString("%1").arg(msg.CANData[7], 2, 16, QChar('0'));
QString MsgInfo = QString("TX-id:%1,dlc:%2,data:%3,Type:%4").arg(QString::number(msg.MsgId,16)) \
.arg(msg.DLC) \
.arg(MsgData) \
.arg(msg.MsgType) ;
ui->textEdit->append(MsgInfo.toUpper());
}
四高蜂,效果
client通過timeout每隔3秒嘗試連接服務(wù)器聪黎,直到連接到服務(wù)器。服務(wù)器是仿真ECU备恤,而client可以理解為平時(shí)使用的canoe上位機(jī)稿饰。ECU接收uds請(qǐng)求72A后發(fā)送78A CAN報(bào)文進(jìn)行回復(fù)。uds就是ECU固件中的c代碼我移植到了Sever中仿真ECU烘跺,讓其通過以太網(wǎng)通信湘纵,好玩吧~
五,小結(jié)
沒想到這小小的多線程socket通信功能弄了我4個(gè)晚上滤淳,主要是線程重構(gòu)及改成pri子工程的設(shè)計(jì)把時(shí)間拉長(zhǎng)了梧喷。