MQTTKit是一個基于Mosquitto庫實現(xiàn)的MQTT協(xié)議網(wǎng)絡(luò)庫,但是已經(jīng)停止更新很久了。日常開發(fā)的功能基本實現(xiàn),但一直未支持TLS/SSL。最近我fork了這個項目并進(jìn)行了修改,截止2017.5.23主要做了以下修改
- 更新Mosquitto庫
- 完成了on_log的回調(diào),可以查看Mosquitto內(nèi)部的打印幫助調(diào)試
- 增添了TLS/SSL的支持
- 細(xì)節(jié)的完善
...
后續(xù)我會檢查原項目里未解決的
issus,并將Mosquitto庫已經(jīng)支持的功能同步過來。項目地址MQTTKit。如果項目需要支持TLS/SSL,你無法直接導(dǎo)入三方框架直接使用,需要進(jìn)行一些配置。這篇文章會介紹如何讓MQTTKit在你的項目中支持TLS/SSL。并給出各種情況下的示例代碼。
將libmosquitto文件夾和MQTTKit文件導(dǎo)入項目,并設(shè)置全局宏WITH_TLS=1

這個時候你編譯程序,會發(fā)現(xiàn)在
mosquitto_internal.h文件里報錯file <openssl.h> not founded。原因在這里官方文檔。Apple認(rèn)為雖然Openssl是一個應(yīng)用非常廣泛的開源庫,但是版本更替其中的API一直變更無法穩(wěn)定。出于這個原因,Openssl不再作為iOS的一部分,即使OS X仍然提供Openssl,但已經(jīng)廢棄了Openssl開源庫。在應(yīng)用開發(fā)中是非常不鼓勵開發(fā)者使用Openssl庫。但是如果我們確實要用的話,應(yīng)該自己編譯OpenSSL代碼,然后靜態(tài)鏈接。具體的操作如下:
- 從OpenSSL-for-iPhone打包下載源碼,解壓到桌面。cd進(jìn)入目錄下執(zhí)行./build-libssl.sh。執(zhí)行完成以后目錄下多了兩個文件夾。

- 將圖中標(biāo)注的兩個文件夾拖入工程。其中include包含的是頭文件,lib包含的是library。

- 加入工程之后我們需要在Build Setting中進(jìn)行設(shè)置,在Header Search Paths中添加include文件夾的路徑
Header Search Paths
Library Search Paths中檢查是否有lib路徑

至此,項目可以完整的運(yùn)行起來。Mosquitto提供了測試的地址。端口1883是普通的服務(wù),無需用戶名密碼即可連接。以下提供了一個簡單的連接測試代碼。
- (void)testConnect
{
client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
client.host = @"test.mosquitto.org";
client.port = 1883;
[client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
if (code == 0)
{
NSLog(@"Connect Success");
}
else
{
NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
}
}];
}
端口8883是單向驗證的接口,你需要驗證服務(wù)器的連接,驗證證書的下載地址。測試代碼如下。我已經(jīng)提前下好證書改名server.crt導(dǎo)入工程。
- (void)testTLSWithOneWayAuthentication
{
client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
client.host = @"test.mosquitto.org";
client.port = 8883;
client.tlsCafile = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"crt"];
[client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
if (code == 0)
{
NSLog(@"Connect Success");
}
else
{
NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
}
}];
}
端口8884需要雙向驗證,客戶端也需要向服務(wù)器提供證書。這個比較麻煩的是需要我們自己生成私鑰和證書,我之前操作的時候遇見了一些麻煩,會在另一篇文章詳細(xì)介紹。這里提供一段測試代碼,其中client.key和client.crt是我已經(jīng)生成的客戶端私鑰和證書
- (void)testTLSWithTwoWayAuthentication
{
client = [[MQTTClient alloc] initWithClientId:[NSString stringWithFormat:@"MQTTKitTests-%@", [[NSUUID UUID] UUIDString]]];
client.host = @"test.mosquitto.org";
client.port = 8884;
client.tlsCerPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"crt"];
client.tlsCerKeyPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"key"];
client.tlsCafile = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"crt"];
client.tlsPeerCertVerify = YES;
[client connectWithCompletionHandler:^(MQTTConnectionReturnCode code) {
if (code == 0)
{
NSLog(@"Connect Success");
}
else
{
NSLog(@"Connect Fail! State Code is %lu", (unsigned long)code);
}
}];
}
后續(xù)我會持續(xù)維護(hù)MQTTKit,如果在使用過程中仍有疑問,或者發(fā)現(xiàn)了任何bug,歡迎在Github和簡書上一起討論解決。
如果對你有所幫助,希望給我一個Star :)
