Qt+webservice的多執行緒實現
專案使用Qt搭建了一個數據庫軟體,需要遠端訪問公司的MES系統,使用webservice技術進行通訊並以XML格式傳輸資料,為了使網路監聽過程中不影響主執行緒程式的正常執行,我們需要將webservice相關功能放在新開的獨立執行緒中。
本專案使用的是QtCreator(Qt5.5.0)+VisualStudio2013+gSOAP2.8搭建。其他版本只要版本是正確對應的,都大同小異。
WebService相關概念
參見參考文獻[3]。
WebService是一種跨程式語言和跨作業系統平臺的遠端呼叫技術。所謂跨程式語言和跨操作平臺,就是說服務端和和客戶端的搭建平臺與程式語言可以都不相同。所謂遠端呼叫,就是一臺計算機a上 的一個程式可以呼叫到另外一臺計算機b上的一個物件的方法。
其實可以從多個角度來理解WebService,從表面上看,WebService就是一個應用程式向外界暴露出一個能通過Web進行呼叫的API,也就是說能用程式設計的方法通過 Web來呼叫這個應用程式。我們把呼叫這個WebService的應用程式叫做客戶端,而把提供這個WebService的應用程式叫做服務端。從深層次看,WebService是建立可互操作的分散式應用程式的新平臺,是一個平臺,是一套標準。它定義了應用程式如何在Web上實現互操作性,你可以用任何 你喜歡的語言,在任何你喜歡的平臺上寫Webservice ,只要我們可以通過Webservice標準對這些服務進行查詢和訪問。
WebService平臺需要一套協議來實現分散式應用程式的建立。任何平臺都有它的資料表示方法和型別系統。要實現互操作性,WebService平臺必須提供一套標準的型別系統,用於溝通不同平臺、程式語言和元件模型中的不同型別系統。Webservice平臺必須提供一種標準來描述Webservice,讓客戶可以得到足夠的資訊來呼叫這個Webservice。最後,我們還必須有一種方法來對這個Webservice進行遠端呼叫,這種方法實際是一種遠端過程呼叫協議(RPC)。為了達到互操作性,這種RPC協議還必須與平臺和程式語言無關。
XML+XSD,SOAP和WSDL就是構成WebService平臺的三大技術。
-
XML+XSD WebService採用HTTP協議傳輸資料,採用XML格式封裝資料(即XML中說明呼叫遠端服務物件的哪個方法,傳遞的引數是什麼,以及服務物件的 返回結果是什麼),XML是WebService平臺中表示資料的格式,其優點在於它既是平臺無關又是廠商無關的。 XML解決了資料表示的問題,但它沒有定義一套標準的資料型別,更沒有說怎麼去擴充套件這套資料型別。例如整形數到底代表什麼?16位,32位,64位?這些細節對實現互操作性很重要。XML Schema(XSD)就是專門解決這個問題的一套標準。它定義了一套標準的資料型別,並給出了一種語言來擴充套件這套資料型別。WebService平臺就是用XSD來作為其資料型別系統的。當你用某種語言(如VB.NET或C#)來構造一個Webservice時,為了符合WebService標準,所有你使用的資料型別都必須被轉換為XSD型別。你用的工具可能已經自動幫你完成了這個轉換,但你很可能會根據你的需要修改一下轉換過程。
-
SOAP SOAP是"簡單物件訪問協議",SOAP協議 = HTTP協議 + XML資料格式。 WebService通過HTTP協議傳送請求和接收結果時,傳送的請求內容和結果內容都採用XML格式封裝,並增加了一些特定的HTTP訊息頭,以說明HTTP訊息的內容格式,這些特定的HTTP訊息頭和XML內容格式就是SOAP協議。SOAP提供了標準的RPC方法來呼叫WebService。 SOAP協議定義了SOAP訊息的格式,SOAP協議是基於HTTP協議的,SOAP也是基於XML和XSD的,XML是SOAP的資料編碼方式。打個比喻:HTTP就是普通公路,XML就是中間的綠色隔離帶和兩邊的防護欄,SOAP就是普通公路經過加隔離帶和防護欄改造過的高速公路。
-
WSDL 好比我們去商店買東西,首先要知道商店裡有什麼東西可買,然後再來購買,商家的做法就是張貼廣告海報。 WebService也一樣,WebService客戶端要呼叫一個WebService服務,首先要有知道這個服務的地址在哪,以及這個服務裡有什麼方法可以呼叫,所以WebService務器端首先要通過一個WSDL檔案來說明自己家裡有啥服務可以對外呼叫,服務是什麼(服務中有哪些方法,方法接受的引數是什麼,返回值是什麼),服務的網路地址用哪個url地址表示,服務通過什麼方式來呼叫。 WSDL(Web Services Description Language)就是這樣一個基於XML的語言,用於描述WebService及其函式、引數和返回值。它是WebService客戶端和伺服器端都能理解的標準格式。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。一些最新的開發工具既能根據你的Webservice生成WSDL文件,又能匯入WSDL文件,生成呼叫相應WebService的代理類程式碼。 WSDL檔案儲存在Web伺服器上,通過一個url地址就可以訪問到它。客戶端要呼叫一個WebService服務之前,要知道該服務的WSDL檔案的地址。 WebService服務提供商可以通過兩種方式來暴露它的WSDL檔案地址:1.註冊到UDDI伺服器,以便被人查詢;2.直接告訴給客戶端呼叫者。
gSOAP總結
gsoap概念:是一種能夠把C/C++語言的介面轉換成基於soap協議的webservice服務的工具。從官網的說明文件可知gSOAP可以為我們完成以下工作:
1、自動生成C和C++原始碼,以使用和部署XML、JSON REST API以及SOAP/XML API; 2、使用gSOAP的快速XML流處理模型進行XML解析和驗證,實現實現可移植的快速的和精簡的API,每秒處理10K+訊息僅需幾KB程式碼和資料; 3、將WSDL轉換為有效的C或C++原始碼以使用或部署XML Web服務; 4、將XML schemas(XSD)轉換為高效的C或C++原始碼,以使用gSOAP全面的XML schemas功能覆蓋來使用或部署XML REST API; 5、為WSDL和/或XSD定義的大型複雜XML規範生成高效的C和C ++程式碼,例如eBay,ONVIF,HL7,FHIR,HIPAA 5010,CDISC,XMPP XEP,TR-069,AWS,EWS,ACORD,ISO 20022和SWIFT,FixML,XBRL,OTA,IATA NDC,FedEx等(您甚至可以將多個組合在一起); 6、安全的XML處理過程:gSOAP不容易受到大部分XML攻擊手段的攻擊; 7、使用強大的XML資料綁定準確地序列化XML中的C和C++資料,這有助於通過靜態型別快速開發型別安全的API,以避免執行時錯誤; 8、在WSDL和XSD檔案上使用wsdl2h選項-O2或-O4進行“schema slicing”,通過自動刪除未使用的schema型別(WSDL和XSD根目錄中無法訪問的型別)來優化XML程式碼庫的大小; 9、使用和部署JSON REST API; 10、使用SAML令牌安全地使用HTTP/S,WS-Security和WS-Trust來使用和部署API; 11、使用測試信使CLI測試您的SOAP/XML API,它會自動生成基於WSDL的完整和隨機化的SOAP/XML訊息(使用帶有選項-g的wsdl2h和soapcpp2)來測試Web服務API和客戶端; 12、使用gSOAP Apache模組在Apache Web伺服器中部署API,在IIS中使用gSOAP ISAPI擴充套件部署API; 13、使用gSOAP cURL外掛和gSOAP WinInet外掛來使用API; 14、符合XML的行業標準,包括XML REST和SOAP,WSDL,MIME,MTOM,DIME,WS-Trust,WS-Security(集成了WS-Policy和WS-SecurityPolicy),WS-ReliableMessaging,WS-Discovery,WS-Addressing等;
gSOAP簡介
gSOAP一種跨平臺的開源的C/C++軟體開發工具包。生成C/C++的RPC程式碼,XML資料繫結,對SOAP Web服務和其他應用形成高效的具體架構解析器,它們都受益於一個XML介面。 這個工具包提供了一個全面和透明的XML資料繫結解決方案,Autocoding節省大量開發時間來執行SOAP/XML Web服務中的C/C++。此外,使用XML資料繫結大大簡化了XML自動對映。應用開發人員不再需要調整應用程式邏輯的具體庫和XML為中心的資料。
gSOAP結構
使用gSOAP首先需要用到了兩個工具就是../gsoap-2.8/gsoap/bin/win32/wsdl2h.exe
和../gsoap-2.8/gsoap/bin/win32/soapcpp2.exe
,用於自動生成包含介面的c/c++原始檔。
wsdl2h.exe
該工具可以根據輸入的wsdl或XSD或URL產生相應的C/C++形式的.h供soapcpp2.exe
使用。示例如下:
新建一個資料夾,將wsdl2h.exe
(和.wsdl
檔案)放入,命令列進入當前路徑後輸入以下命令:
wsdl2h [options] XSD and WSDL files ...
wsdl2h -o file.h file1.wsdl
wsdl2h -o file.h http://www.genivia.com/calc.wsdl
根據WSDL自動生成file.h
標頭檔案,以供soapcpp2.exe
使用。
wsdl2h主要的執行選項如下:
選項 | 描述 |
---|---|
-a | 對匿名型別產生基於順序號的結構體名稱 |
-b | 提供單向響應訊息的雙向操作(雙工) |
-c | 生成c程式碼 |
-c++ | 生成c++程式碼 |
-c++11 | 生成c++11程式碼 |
-d | 使用DOM填充xs:any和xsd:anyType元素 |
-D | 使用指標使具有預設值的屬性成員可選 |
-e | 不要限定列舉名稱,此選項用於向後相容gSOAP 2.4.1及更早版本,該選項不會生成符合WS-I Basic Profile 1.0a的程式碼。 |
-f | 為schema擴充套件生成平面C++類層次結構 |
-g | 生成全域性頂級元素宣告 |
-h | 顯示幫助資訊 |
-I path | 包含檔案時指明路徑,相當於#import |
-i | 不匯入(高階選項) |
-j | 不生成SOAP_ENV__Header和SOAP_ENV__Detail定義 |
-k | 不生成SOAP_ENV__Header mustUnderstand限定符 |
-l | 在輸出中包含許可證資訊 |
-m | 使用xsd.h模組匯入基元型別 |
-N name | 用name 來指定服務名稱空間的字首 |
-n name | 用name 作為名稱空間的字首取代預設的ns |
-O1 | 通過省略重複的選擇/序列成員來優化 |
-O2 | 優化-O1並省略未使用的模式型別(從根目錄無法訪問) |
-o file | 輸出檔名 |
-P | 不要建立從xsd__anyType繼承的多型型別 |
-p | 建立從base xsd__anyType繼承的多型型別,當WSDL包含多型定義時,會自動執行此操作 |
-q name | 使用name作為所有宣告的C++名稱空間 |
-R | 在WSDL中為REST繫結生成REST操作 |
-r host[:port[:uid:pwd]] | 通過代理主機,埠和代理憑據連線 |
-r:uid:pwd | 連線身份驗證憑據(驗證身份驗證需要SSL) |
-s | 不生成STL程式碼(沒有std :: string和沒有std :: vector) |
-t file | 使用型別對映檔案而不是預設檔案typemap.dat |
-U | 將Unicode XML名稱對映到UTF8編碼的Unicode C/C++識別符號 |
-u | 不產生工會unions |
-V | 顯示當前版本並退出 |
-v | 詳細輸出 |
-W | 抑制編譯器警告 |
-w | 始終在響應結構中包裝響應引數 |
-x | 不生成_XML any/anyAttribute可擴充套件性元素 |
-y | 為結構和列舉生成typedef同義詞 |
soapcpp2.exe
該工具是一個根據.h檔案生成若干支援webservice程式碼檔案生成工具,生成的程式碼檔案包括webservice客戶端和服務端的實現框架,XML資料繫結等,具體說明如下:
新建一個資料夾,將soapcpp2.exe
和.h
檔案放入,命令列進入當前路徑後輸入以下命令:
soapcpp2 [options] header_file.h
soapcpp2 mySoap.h
soapcpp2 -c -r -CL calc.h
會生成如下c型別檔案:
使用命令-i
會生成如下c++型別檔案:
檔案 | 描述 |
---|---|
soapStub.h | 根據輸入的.h檔案生成的資料定義檔案,一般我們不直接引用它 |
soapH.h | 所有客戶端服務端都應包含的主標頭檔案 |
soapC.cpp | 指定資料結構的序列化和反序列化方法 |
soapClient.cpp | 用於遠端操作的客戶端存根例程 |
soapServer.cpp | 服務框架例程 |
soapClientLib.cpp | 客戶端存根與本地靜態(反)序列化器結合使用 |
soapServerLib.cpp | 服務框架與本地靜態(反)序列化器結合使用 |
soapXYZProxy.h | 使用選項-i:c++服務端物件(與soapC.cpp和soapXYZProxy.cpp連結) |
soapXYZProxy.cpp | 使用選項-i:客戶端程式碼 |
soapXYZService.h | 使用選項-i:server物件(與soapC.cpp和soapXYZService.cpp連結) |
soapXYZService.cpp | 使用選項-i:服務端程式碼 |
.xsd | ns.XSD由XML Schema生成,ns為名稱空間字首名,我們可以看看是否滿足我們的協議格式(如果有此要求) |
.wsdl | ns.wsdl由WSDL描述生成 |
.xml | 生成了幾個SOAP/XML請求和響應檔案。即滿足webservice定義的例子message(實際的傳輸訊息),我們可以看看是否滿足我們的協議格式(如果有此要求) |
.nsmap | 根據輸入soapcpp2.exe的標頭檔案中定義的名稱空間字首ns生成ns.nsmap,該檔案包含可在客戶端和服務端使用的名稱空間對映表 |
soapcpp的主要執行選項如下:
選項 | 描述 |
---|---|
-1 | 生成SOAP 1.1繫結 |
-2 | 生成SOAP 1.2繫結 |
-0 | 沒有SOAP繫結,使用REST |
-C | 僅生成客戶端程式碼 |
-S | 僅生成服務端程式碼 |
-T | 生成服務端自動測試程式碼 |
-Ec | 為深度資料複製生成額外的例程 |
-Ed | 為深度資料刪除生成額外的例程 |
-Et | 使用walker函式為資料遍歷生成額外的例程 |
-L | 不生成soapClientLib / soapServerLib |
-a | 使用SOAPAction和WS-Addressing來呼叫服務端操作 |
-A | 要求SOAPAction呼叫服務端操作 |
-b | 序列化位元組陣列char [N]為字串 |
-c | 生成純C程式碼 |
-d | 儲存到指定目錄 |
-e | 生成SOAP RPC編碼樣式繫結 |
-f N | 多個soapC檔案,每個檔案有N個序列化程式定義(N≥10) |
-h | 列印一條簡短的用法訊息 |
-i | 生成從soap struct繼承的服務代理類和物件 |
-j | 生成可以共享soap結構的C++服務代理類和物件 |
-I | 包含其他檔案時使用,指明 < path > (多個的話,用`:'分割),相當於#import ,該路徑一般是gSOAP目錄下的import目錄,該目錄下有一堆檔案供soapcpp2生成程式碼時使用 |
-l | 生成可連結模組(實驗) |
-m | 為MEX編譯器生成Matlab程式碼 |
-n | 用於生成支援多個客戶端和伺服器端 |
-p | 生成的檔案字首採用< name > ,而不是預設的 “soap” |
-q | 使用name作為c++所有宣告的名稱空間 |
-r | 生成soapReadme.md報告 |
-s | 生成的程式碼在反序列化時,嚴格檢查XML的有效性 |
-t | 生成的程式碼在傳送訊息時,採用xsi:type方式 |
-u | 通過抑制XML註釋來取消註釋WSDL / schema輸出中的註釋 |
-V | 顯示當前版本並退出 |
-v | 詳細輸出 |
-w | 不生成WSDL和schema檔案 |
-x | 不生成示例XML訊息檔案 |
-y | 在示例XML訊息中包含C / C ++型別訪問資訊 |
例項介紹
功能介紹
1、客戶端能夠向服務端傳送字串資料; 2、服務端能夠接收到客戶端傳送的字串資料; 3、服務端對字串資料解析、查重並錄入資料庫; 4、軟體視窗顯示連線狀態。
最終效果如下所示: 點選“開始連線”按鈕:
從客戶端接收到一組資料後:
例項步驟
1. 生成原始碼
由於沒有.wsdl
檔案,因此我們跳過wsdl2h.exe
這一步驟,手動編寫供soapcpp2.exe
使用的標頭檔案mySoap.h
:
//gsoap ns service name: sendMsg
//gsoap ns service style: rpc
//gsoap ns service encoding: encoded
//gsoap ns service namespace: urn:sendMsg
int ns__sendMsg(char* szMsgXml,struct nullResponse{} *out);
新建資料夾,將soapcpp2.exe
和mySoap.h
放入,開啟命令後進入該目錄下,執行命令soapcpp2 mySoap.h
,生成如下檔案:
2. 客戶端程式編寫
在QtCreator中向客戶端工程目錄新增檔案sendMsg.nsmap
、soapH.h
、soapStub.h
、stdsoap2.h
、soapC.cpp
、soapClient.cpp
、stdsoap2.cpp
(stdsoap2.h
和stdsoap2.cpp
位於資料夾../gsoap-2.8/gsoap
)。
客戶端專案構建的是一個控制檯程式,因此直接在main函式裡進行編寫程式碼:
#include <QCoreApplication>
#include "stdio.h"
#include "gservice.nsmap"
#include "soapStub.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
printf("The Client is runing...\n");
struct soap *CalculateSoap = soap_new();
char server_addr[] = "127.0.0.1:8080"; // url地址,IP號+裝置埠號
char* data = "flange,6,7,8,9,10,11,12,13"; // 所需傳遞的資料
nullResponse result; // 用於sendMsg的空返回值
int iRet = soap_call_ns__sendMsg(CalculateSoap,server_addr,NULL,data,&result); // 呼叫之前定義的ns__sendMsg方法(即服務端提供的方法)
if ( iRet == SOAP_ERR){
printf("Error while calling the soap_call_ns__sendmsg");
}
else
{
printf("Calling the soap_call_ns__add success。\n");
}
soap_end(CalculateSoap);
soap_done(CalculateSoap);
return a.exec();
}
3. 服務端程式編寫
在QtCreator中向服務端工程目錄新增檔案sendMsg.nsmap
、soapH.h
、soapStub.h
、stdsoap2.h
、soapC.cpp
、soapServer.cpp
、stdsoap2.cpp
。
由於服務端網路通訊功能需要不斷對埠進行監聽,因此為避免影響軟體其他功能的執行,在此需要新開一條執行緒。專案標頭檔案原始碼如下: socketconnect.h:
#ifndef SOCKETCONNECT_H
#define SOCKETCONNECT_H
#include <QWidget>
#include <QDebug>
#include <QVector>
#include "webservice_thread.h" // 多執行緒標頭檔案
#include <QMessageBox>
namespace Ui {
class SocketConnect;
}
class SocketConnect : public QWidget
{
Q_OBJECT
public:
void setDbconn(QSqlDatabase *dbconn); // 主執行緒資料庫
explicit SocketConnect(QWidget *parent = 0);
~SocketConnect();
private slots:
void pB_lj_clicked(); // 連線按鈕
void pB_dk_clicked(); // 斷開連線按鈕
void linkState_accept(QVector<QString>); // 用於在視窗顯示連線狀態
void data_accept(QVector<QString>); // 接收資料,檢查後錄入資料庫
private:
QSqlDatabase *dbconn;
WebserviceThread *WebT;
QVector<QString> v_linkstate;
Ui::SocketConnect *ui;
};
#endif // SOCKETCONNECT_H
socketconnect.cpp:
#include "socketconnect.h"
#include "ui_socketconnect.h"
#include "scrollwidget.h"
SocketConnect::SocketConnect(QWidget *parent) :
QWidget(parent),
ui(new Ui::SocketConnect)
{
ui->setupUi(this);
ui->tabWidget->setTabText(1, QStringLiteral("法蘭盤部件"));
ui->tabWidget->setCurrentIndex(0);
ui->lineEdit->setText("127.0.0.1"); // 暫時無用
ui->lineEdit_2->setText("8080");
ui->lineEdit_3->setText("helloworld");
ui->lineEdit_4->setText("helloworld");
ui->lineEdit_4->setEchoMode(QLineEdit::Password);
ui->tableWidget_fla->setEditTriggers(QAbstractItemView::NoEditTriggers); // 表格不可編輯
ui->tableWidget_fla->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget_fla->setAlternatingRowColors(true);
ui->tableWidget_fla->setStyleSheet("QTableView{alternate-background-color: rgb(183, 242, 238);}"); // 設定隔行換色
connect(ui->pushButton_lj,SIGNAL(clicked(bool)),this,SLOT(pB_lj_clicked()));
connect(ui->pushButton_dk,SIGNAL(clicked(bool)),this,SLOT(pB_dk_clicked()));
}
SocketConnect::~SocketConnect()
{
delete ui;
}
void SocketConnect::setDbconn(QSqlDatabase *db){
this->dbconn=db;
}
void SocketConnect::pB_lj_clicked()
{
if(ui->lineEdit_3->text()=="helloworld"&&ui->lineEdit_4->text()=="helloworld"){
WebT = new WebserviceThread(this);
int port = ui->lineEdit_2->text().toInt();
WebT->setParameters(port);
connect(WebT,SIGNAL(linkState_send(QVector<QString>)),this,SLOT(linkState_accept(QVector<QString>)));
connect(ui->pushButton_dk,SIGNAL(clicked(bool)),WebT,SLOT(stopclick_accept()));
connect(WebT,SIGNAL(data_send(QVector<QString>)),this,SLOT(data_accept(QVector<QString>)));
WebT->start(); // 進入執行緒
}
else{
QMessageBox::critical(NULL, QString::fromLocal8Bit("警告"), QStringLiteral("賬號或密碼錯誤,無法連線!"), QMessageBox::Yes);
}
}
void SocketConnect::linkState_accept(QVector<QString> link_state){
ScrollWidget *s_linkstate = new ScrollWidget; // 自己定義的QWidget的子類,用於增加、更新、清空QList<QWidget*>
QString linkstate;
for(int i=0;i<link_state.size();i++){
linkstate+=link_state[i];
}
v_linkstate.append(linkstate); // 儲存執行緒檔案傳過來的連線狀態
for(int i=0;i<v_linkstate.size();i++){
QLabel *label_linkstate = new QLabel(v_linkstate[i]);
s_linkstate->addWidget(label_linkstate);
}
s_linkstate->updateWidget();
ui->scrollArea->setWidget(s_linkstate); // 更新scrollarea
}
void SocketConnect::data_accept(QVector<QString> content){
dbconn->open();
QString dataClass = content[0]; // 第一個資料儲存了資料型別資訊
content.erase(content.begin());
//檢查編號資料是否重複或為空
dbconn->open();
if(content[0].isEmpty()){
QMessageBox::critical(NULL, QString::fromLocal8Bit("警告"), QStringLiteral("遠端傳輸資料的編號為空,請檢查並重新錄入!"), QMessageBox::Yes);
return;
}
QSqlQueryModel *model_sql = new QSqlQueryModel;
model_sql->setQuery(QString("SELECT * FROM wbq.%1").arg(dataClass));
for(int k=0 ;k<model_sql->rowCount(); k++){
QModelIndex index = model_sql->index(k,0);
if(content[0] == model_sql->data(index).toString()){
QMessageBox::critical(NULL, QString::fromLocal8Bit("警告"), QStringLiteral("遠端傳輸資料的編號已存在於資料庫中,請檢查並重新錄入!"), QMessageBox::Yes);
return;
}
}
//結束檢查
if(dataClass=="flange"){
ui->tabWidget->setCurrentIndex(1);
//資料寫入MySQL資料庫
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(QStringLiteral("INSERT INTO wbq.coordinator SET 編號=%1, ......").arg(content[0])......; // 輸入資料
dbconn->close();
delete model;
//資料顯示到表格中
int row = ui->tableWidget_fla->rowCount()+1;
ui->tableWidget_fla->setRowCount(row);
for(int i=0;i<content.size();i++){
ui->tableWidget_fla->setItem(row-1,i,new QTableWidgetItem);
ui->tableWidget_fla->item(row-1,i)->setText(content[i]);
}
}
else{
QMessageBox::critical(NULL, QString::fromLocal8Bit("警告"), QStringLiteral("資訊格式有誤或資訊錯誤!"), QMessageBox::Yes);
}
}
void SocketConnect::pB_dk_clicked()
{
ui->scrollArea->takeWidget();
QVector<QString> tmp;
v_linkstate.swap(tmp);
ui->tableWidget_fla->setRowCount(0);
}
多執行緒標頭檔案webservice_thread.h:
#ifndef WEBSERVICE_THREAD
相關推薦
Qt+webservice的多執行緒實現
專案使用Qt搭建了一個數據庫軟體,需要遠端訪問公司的MES系統,使用webservice技術進行通訊並以XML格式傳輸資料,為了使網路監聽過程中不影響主執行緒程式的正常執行,我們需要將webservice相關功能放在新開的獨立執行緒中。
本專案使用的是QtCre
Qt中採用多執行緒實現Socket程式設計
本文介紹的是Qt中採用多執行緒Socket程式設計,由於工作專案的需要,使用Qt的socket程式設計。Qt裡的example是個不錯的教程,但是當我把程式碼移植
基於QT的多執行緒視訊監控的實現(二)
二丶接著上一節,這節主要講,多屏分割,多屏相互切換 視訊監控很重要的一個環節就是多屏切換了,這裡主要實現的是 1,2,4,8,16,32,64 分屏的相互切換,最多是64分屏。(1)QT 常用到的佈
Java多執行緒實現電影院售票案例
某電影院目前正在上映賀歲大片,共有100張票,而它有3個售票視窗,請設計一個程式模擬該電影院售票。
定義Sell類實現Runnable介面,很好的解決了單繼承共享資源問題
public class Sell implements Runnable {
// 定義100張票,三個售票
Java 多執行緒實現死鎖場景
簡述:
《Java 程式設計思想》 P718 ~ P722
模擬死鎖的場景, 三個人 三根筷子,每個人需要拿到身邊的兩根筷子才能開始吃飯
出現死鎖的場景是,三個人都拿到了右邊的筷子,但是由於筷子都被搶佔,均無法獲得左邊的筷子
Chopstick.java
【Java筆記】多執行緒實現簡單的非同步運算
實現Callable介面,重寫call()方法,使操作執行緒池時能帶有返回值的效果:
import java.util.concurrent.Callable;
public class GetSumCallable implements Callable<Integer> {
二、多執行緒實現簡單的socket通訊例項(TCP)
1.伺服器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 類功能描述:先啟動伺服器端,再啟動客戶端
*
* @author:***
* @createTime:2018/
利用python多執行緒實現區塊鏈paxos演算法解決使用者共識
本來是做python 開發的老闆最近讓做區塊鏈也沒有頭緒從網上找了點視訊看著照的敲了了下感覺是自己寫過最多的程式碼啦 怪我才疏學淺 哈哈哈--
import threading, socket, pickle, queue
class Message(object):
MS
python 通過多執行緒實現Excel 批量更新商品價格
import openpyxl
import threading
wb = openpyxl.load_workbook('produceSales.xlsx')
sheet = wb.active
all_info = []
for row in sheet.rows:
child
多執行緒實現UDP協議傳送、接收資料
放碼過來吧!
public class ChatRoom {
public static void main(String[] args) throws SocketException {
DatagramSocket sendSocket =
MySQL 原始碼分析 Innodb緩衝池刷髒的多執行緒實現
簡介
為了提高效能,大多數的資料庫在操作資料時都不會直接讀寫磁碟,而是中間經過緩衝池,將要寫入磁碟的資料先寫入到緩衝池裡,然後在某個時刻後臺執行緒把修改的資料刷寫到磁碟上。MySQL的InnoDB引擎也使用緩衝池來快取從磁碟讀取或修改的資料頁,如果當前資料庫需要操作的資料集比緩衝池中的空閒頁面大
Python進階(二十六)-多執行緒實現同步的四種方式
分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow
也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/mm2zzyzzp
Python進階(二十六)-多執行緒實現同步的四種方式
多執行緒實現udp網路通訊
本章節將介紹主執行緒與子執行緒的關係;使用udp利用多執行緒在python環境下實現全雙工通訊程式碼的兩種實現。(未完待續。。。)
一、主執行緒與子執行緒的關係:
1,若主執行緒無程式碼執行,主執行緒將等待子執行緒結束而結束。
2,執行緒的執行並無先後順序。
3,若主執行緒因特殊原因先結束,子執行緒也
java:多執行緒(實現Runnable的原理)及二種方式的區別
* 1,看Thread類的建構函式,傳遞了Runnable介面的引用 * 2,通過init()方法找到傳遞的target給成員變數的target賦值 * 3,檢視run方法,發現run方法中有判斷,如果target不為null就會呼叫Runnable介面子類物件的run方法
*
QT學習(五)QT之多執行緒
1. 執行緒同時進行
QT提供了QThread來定義一個執行緒,我們通過定義類thread來重新實現它。
classThread:publicQThread
{
Q_OBJECT
public:
&nbs
多執行緒實現通訊
&nb
多執行緒實現存款取款
多執行
多執行緒實現Runnable介面
package com.lxxu.testthread;
class MyThread2 implements Runnable{//執行緒的主體類
private String title;
public MyThread2(String title){
this.title = tit
QT C++ 多執行緒多串列埠介面設計
忙了兩三天了,總算得空記錄一下QT串列埠,文末會有總的工程檔案上傳,多謝大家捧場。 之前博文寫過PyQT,目前我逐漸偏向C++了,但主要程式碼思想沒有變,如下:
第一,在QTdesigner下,建立好UI,如下圖(右下角是我自己的小公司,留個爪印哈): UI細節就不詳細說了,
java socket多執行緒實現聊天室
java socket多執行緒實現聊天室
程式碼放在我的GitHub上點選檢視
版本1,一對一,收發有順序
/**
* @Author: Hzw
* @Time: 2018/4/19 11:38
* @Description: 聊天室客戶端V1.0,雙向通訊,客戶端傳