[Qt開發(fā)/畢業(yè)設(shè)計(jì)/求職項(xiàng)目]局域網(wǎng)環(huán)境下遠(yuǎn)程文件發(fā)送部署系統(tǒng)-服務(wù)端、客戶端雙端的
B站專欄不支持MD語法,為了更好的體驗(yàn)請(qǐng)移步本人博客
[Qt開發(fā)/畢業(yè)設(shè)計(jì)/求職項(xiàng)目]局域網(wǎng)環(huán)境下遠(yuǎn)程文件發(fā)送部署系統(tǒng)-服務(wù)端、客戶端雙端的講解
https://www.cnblogs.com/Leventure/p/17129442.html
## 寫在前面
本文旨在做一個(gè)簡(jiǎn)單的代碼講解,我會(huì)給出源碼,然后整個(gè)代碼的講解都在源碼的基礎(chǔ)上進(jìn)行。
代碼可能會(huì)隨著更新而進(jìn)行修改,但是整體框架變化不會(huì)太大。
整個(gè)文章內(nèi)容不會(huì)太多,算是我自己的一個(gè)復(fù)盤,整個(gè)的來說算是一個(gè)比較綜合的程序開發(fā),不算太難,但對(duì)于初學(xué)者來說肯定也不會(huì)太簡(jiǎn)單。程序涉及到網(wǎng)絡(luò)模塊、自定義UI、文件讀寫等內(nèi)容,但是比較可惜的是作為一個(gè)Windows桌面端程序沒有涉及到Windows窗體和COM組件,這個(gè)是我覺得比較可惜的。
綜上,本文不是零基礎(chǔ)的項(xiàng)目講解和代碼教學(xué),請(qǐng)至少參考一下下列的確定任務(wù)環(huán)節(jié),確定自己能看明白需要做些什么再繼續(xù)閱讀本文。
注:我寫到一般發(fā)現(xiàn)用文字和圖片來寫教程實(shí)在是太折磨了,所以我想偷懶一下直接用視頻去講解,如果急得話可以直接拿我的源碼去看,要是不急的話可以直接b站關(guān)注我,B站ID:Leventure_軒先生
[B站主頁(yè):Leventure_軒先生](https://space.bilibili.com/3343831)
Github:?
服務(wù)端:https://github.com/LeventureQys/FilePlanter
客戶端:https://github.com/LeventureQys/FilePlanterClient
## 確定任務(wù)
按照我們的標(biāo)題,是要做一個(gè)局域網(wǎng)環(huán)境下的遠(yuǎn)程文件發(fā)送部署工具,那么我們需要確定一下基本知識(shí)。
1.使用的是Qt開發(fā),所以基本的ui要會(huì)用,包括基本的控件,自定義的控件,選擇文件等等。包括信號(hào)槽機(jī)制
2.需要了解最基本的文件IO,至少你得知道在本案例中,文件是通過二進(jìn)制字符流進(jìn)行的傳輸
3.需要了解一些最基本的網(wǎng)絡(luò)知識(shí),TCP和UDP的協(xié)議你至少得知道是什么東西,了解socket通信
4.需要了解什么是注冊(cè)表,因?yàn)槠渲杏行┎僮餍枰x寫注冊(cè)表。
ok,在我們知道閱讀本文需要知道哪些知識(shí)之后,接下來就說說怎么做這個(gè)程序。
## 做什么?怎么做?
### 做什么?
整個(gè)系統(tǒng)由兩個(gè)軟件組成,分別是文件部署服務(wù)端及文件部署客戶端。我們將一個(gè)文件從服務(wù)端發(fā)送到很多個(gè)連接到當(dāng)前服務(wù)端的客戶端的指定路徑上去。這個(gè)是我們的目標(biāo)
### 怎么做?
### 發(fā)送端:
1.我們需要一個(gè)最基本的界面框架,如下

2.因?yàn)槲募掳l(fā)可能會(huì)需要面向不同的對(duì)象,所以我們可能需要一個(gè)自定義的用戶對(duì)象ui,用于插入到界面ui的右方,如圖所示:

用戶對(duì)象的ui需要提供一些最基本的功能,包括展示指定用戶的信息、可以踢出用戶、重新發(fā)送文件、展示當(dāng)前用戶的發(fā)送進(jìn)度等等。
3.需要一個(gè)最基本的TCP連接模塊。
4.需要自己來定義一個(gè)簡(jiǎn)單的文件切分的協(xié)議。
### 接收端:
1.同樣的需要一個(gè)簡(jiǎn)單的界面

功能比較簡(jiǎn)單,只需要提供服務(wù)端的IP,和一個(gè)自身的唯一標(biāo)識(shí),提供一個(gè)文件保存路徑即可
2.要能夠讀寫注冊(cè)表,令自己能夠是開機(jī)啟動(dòng)(注:開機(jī)啟動(dòng)的程序的依賴需要放在指定位置,具體內(nèi)容請(qǐng)查詢百度)
3.要有一個(gè)讀寫接收服務(wù)端二進(jìn)制流的網(wǎng)絡(luò)服務(wù)DLL
4.要有一個(gè)能夠解析這個(gè)二進(jìn)制流與服務(wù)端相對(duì)的簡(jiǎn)單協(xié)議。
## 開始著手做
### 一、最基本的出發(fā):網(wǎng)絡(luò)協(xié)議
整個(gè)軟件最最底層的功能自然是網(wǎng)絡(luò)連接,如果連最起碼的網(wǎng)絡(luò)連接都沒有,更不要談后續(xù)的開發(fā)了。實(shí)際上整個(gè)軟件都是建立在這個(gè)網(wǎng)絡(luò)協(xié)議能夠順利進(jìn)行并收發(fā)信息的基礎(chǔ)上。也就是說即使我們整個(gè)程序用的是黑板命令行也可以運(yùn)行,但是如果沒有這個(gè)網(wǎng)絡(luò)協(xié)議,那么整個(gè)程序就無法正常進(jìn)行了。
網(wǎng)絡(luò)通信模塊的詳情見Github:
[LgQtNetwork](https://github.com/LeventureQys/LgQtNetwork/tree/main/LgQtNetwork)
這個(gè)倉(cāng)庫(kù)里面包含了服務(wù)端和客戶端兩邊,接下來我要對(duì)代碼進(jìn)行簡(jiǎn)單的講解。
注:整個(gè)通訊庫(kù)使用的是Qt的類,需要在模塊里加上一個(gè)network并使用到相關(guān)的模塊,所有的行為都托管交給了Qt的內(nèi)部去處理,所以這里不存在丟包、粘包的處理,統(tǒng)一交給Qt的lib去管理了。
### TCP協(xié)議
1.發(fā)送端:
Socket通訊可以理解為單純地發(fā)送一些數(shù)據(jù)包,這些數(shù)據(jù)包中只有內(nèi)容,并沒有包括但不限于字符總長(zhǎng)度、當(dāng)前字符位置、第幾個(gè)包等這些信息,這些信息可能統(tǒng)統(tǒng)需要我們自己去定義。
首先我們知道,我們不可能把一個(gè)socket包定義的太大,比如一次發(fā)幾十上百萬個(gè)字節(jié),這是顯然不可能的,這樣操作的話會(huì)使得我們的tcp連接性能變差而且丟包的損失嚴(yán)重。而且數(shù)字是由順序的,但是網(wǎng)絡(luò)連接不一定能夠保證所有的順序都保持勻速運(yùn)轉(zhuǎn),可能有的快有的慢——那我們數(shù)據(jù)的順序又該如何保證呢?
當(dāng)然了這些問題我們這里是不考慮的,一部分是我不懂,另一部分是這里太小了寫不下(笑
不急,我們一步步來
1>首先要建立一個(gè)QTcpServer的實(shí)例對(duì)象,然后讓它去監(jiān)聽端口:


綁定新用戶登錄的事件,每當(dāng)一個(gè)新用戶進(jìn)入之后,就通過一個(gè)結(jié)構(gòu)體登記這個(gè)用戶并把它記錄在一個(gè)哈希表中方便通過其唯一ID來搜索這個(gè)用戶
哈希表:

用戶結(jié)構(gòu)體:

進(jìn)行信號(hào)的綁定,方便后續(xù)對(duì)外提供接口:

如何發(fā)送TCP消息給其他客戶端,主要是看這個(gè)SendMsg:

這個(gè)SendMsg是另一個(gè)方法,可以按F12走進(jìn)去看下:

這里其實(shí)相當(dāng)于就是簡(jiǎn)單處理了以下,把這個(gè)二進(jìn)制流的消息分段1024個(gè)字節(jié)為一組打包發(fā)送,通過TcpServer的write方法發(fā)送指定長(zhǎng)度的字節(jié)
TCP消息的接受也是類似,包括客戶端的TCP消息收發(fā)也是類似的,唯一的不同就是一個(gè)是TCP的服務(wù)端,一個(gè)是TCP的客戶端,一個(gè)是監(jiān)聽等待客戶連接,一個(gè)是客戶端主動(dòng)連接等到服務(wù)端返回,有點(diǎn)區(qū)別,但區(qū)別不大。