進(jìn)行Socket編程, 常見(jiàn)使用的協(xié)議UDP/TCP
TCP:傳輸控制協(xié)議 肘习。是專(zhuān)門(mén)設(shè)計(jì)用于在不可靠的因特網(wǎng)上提供可靠的绷蹲,端到端的字節(jié)流通信的協(xié)議蹋宦。它是一種面向連接的協(xié)議。TCP連接是字節(jié)流而非報(bào)文流赌髓。
UDP:用戶(hù)數(shù)據(jù)報(bào)協(xié)議 从藤。不需要建立連接,不可靠锁蠕。
iOS中Socket編程
●BSD Socket
BSD Socket 是UNIX系統(tǒng)中通用的網(wǎng)絡(luò)接口夷野,它不僅支持各種不同的網(wǎng)絡(luò)類(lèi)型,而且也是一種內(nèi)部進(jìn)程之間的通信機(jī)制荣倾。在我們iOS中也可以使用扫责,但是它所有的函數(shù)都是基于C語(yǔ)言的,所有在實(shí)際的項(xiàng)目開(kāi)發(fā)中逃呼,我們都是使用封裝好的鳖孤。
●CFSocket
CFSocket是蘋(píng)果官方提供給我們進(jìn)行Socket編程者娱,里面還是有很多C語(yǔ)言的東西,使用起來(lái)稍微麻煩一點(diǎn)苏揣。
●AsyncSocket
AsyncSocket是一個(gè)開(kāi)源的庫(kù)黄鳍,用來(lái)進(jìn)行iOS的Socket編程就非常方便, 但是目前只有OC版本, 并且長(zhǎng)時(shí)間沒(méi)有更新
●ysocket
目前使用Swift進(jìn)行Socket編程時(shí),常用的一個(gè)庫(kù)
消息傳輸
TCP在傳輸數(shù)據(jù)時(shí),傳輸?shù)氖亲止?jié)流
在讀取消息時(shí),需要知道數(shù)據(jù)的長(zhǎng)度, 否則就會(huì)出現(xiàn)讀取不完整或者讀取長(zhǎng)度過(guò)多的情況, 因此讀取方法要求我們傳入本次讀取的消息長(zhǎng)度
如何解決該問(wèn)題呢?
方案一: 客戶(hù)端發(fā)送兩次消息
消息一是記錄后續(xù)消息長(zhǎng)度, 消息二是真正的消息
方案二: 客戶(hù)端發(fā)送一次消息
消息有一個(gè)Header,用于記錄消息的長(zhǎng)度, 后續(xù)為真實(shí)消息內(nèi)容
消息類(lèi)型
開(kāi)發(fā)中經(jīng)常遇到類(lèi)似這樣的場(chǎng)景:
我們的客戶(hù)端是使用Swift/OC/Java來(lái)寫(xiě)的, 可以運(yùn)行在不同的平臺(tái), iOS/Android/Window/Linux.服務(wù)器基于Linux平臺(tái)并使用C++開(kāi)發(fā)完成的, 兩種程序之間采用什么進(jìn)行通信呢?
- 直接傳遞C/C++語(yǔ)言中一字節(jié)對(duì)齊的結(jié)構(gòu)體數(shù)據(jù),只要結(jié)構(gòu)體的聲明為定長(zhǎng)格式平匈,那么該方式對(duì)于C/C++程序而言就非常方便了, 但是對(duì)于java這種不常用結(jié)構(gòu)體的語(yǔ)言, 處理起來(lái)就相當(dāng)麻煩
- 使用SOAP協(xié)議(WebService)作為消息報(bào)文的格式載體框沟,由該方式生成的報(bào)文是基于文本格式的,同時(shí)還存在大量的XML描述信息增炭,因此將會(huì)大大增加網(wǎng)絡(luò)IO的負(fù)擔(dān)忍燥。又由于XML解析的復(fù)雜性,這也會(huì)大幅降低報(bào)文解析的性能隙姿∶仿ⅲ總之,使用該設(shè)計(jì)方式將會(huì)使系統(tǒng)的整體運(yùn)行性能明顯下降输玷。
- Json交換格式, 目前比較理想的一種通信格式, 也是在Http請(qǐng)求數(shù)據(jù)時(shí), 最常見(jiàn)的用法(Demo程序)
- ProtocolBuffer(也稱(chēng)PB/GPB): google 的一種數(shù)據(jù)交換的格式, 可以實(shí)現(xiàn)跨平臺(tái), 方便的序列化&反序列化, 并且數(shù)據(jù)量相對(duì)json
Json/GPB對(duì)比優(yōu)缺點(diǎn)對(duì)比
- 跨平臺(tái)
ProtoBuf支持多平臺(tái)和語(yǔ)言, 包括C++/Java/Python等等- 序列化&反序列號(hào)
ProtoBuf支持直接將對(duì)象序列化成Data, 也支持直接將Data序列化為對(duì)象類(lèi)型- 消息大小
一條消息數(shù)據(jù)队丝,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一欲鹏,是二進(jìn)制序列化的10分之一
對(duì)于即時(shí)通信消息來(lái)說(shuō), 減小數(shù)據(jù)量的大小非常有必須
主題:
ProtocolBuffer使用
1.ProtocolBuffer環(huán)境安裝
How To Install Protobuf Compiler from Homebrew
1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.brew install protobuf-swift
How To Install Protobuf Compiler
1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.brew install automake
3.brew install libtool
4.brew install protobuf
5.git clone git@github.com:alexeyxo/protobuf-swift.git
6../scripts/build.sh
Add ./src/ProtocolBuffers/ProtocolBuffers.xcodeproj in your project.
2.ProtocolBuffer的使用
2.1 創(chuàng)建.proto文件
在項(xiàng)目中, 創(chuàng)建一個(gè)(或多個(gè)).proto文件
之后會(huì)通過(guò)該文件, 自動(dòng)幫我們生成需要的源文件(比如C++生成.cpp源文件, 比如java生成.java源文件, Swift就生成.swift源文件)
3.jpg
4.png
源碼規(guī)范
syntax = "proto2";
message GiftMessage {
required int64 id = 1;
required string name = 2;
optional string email = 3;
}
具體說(shuō)明
● syntax = "proto2"; 為定義使用的版本號(hào), 目前常用版本proto2/proto3
● message是消息定義的關(guān)鍵字机久,等同于C++/Swift中的struct/class,或是Java中的class
● Person為消息的名字赔嚎,等同于結(jié)構(gòu)體名或類(lèi)名
● required前綴表示該字段為必要字段膘盖,既在序列化和反序列化之前該字段必須已經(jīng)被賦值
● optional前綴表示該字段為可選字段, 既在序列化和反序列化時(shí)可以沒(méi)有被賦值
● repeated通常被用在數(shù)組字段中
● int64和string分別表示整型和字符串型的消息字段
● id和name和email分別表示消息字段名,等同于Swift或是C++中的成員變量名
● 標(biāo)簽數(shù)字1和2則表示不同的字段在序列化后的二進(jìn)制數(shù)據(jù)中的布局位置, 需要注意的是該值在同一message中不能重復(fù)
2.2 .代碼編寫(xiě)完成后, 生成對(duì)應(yīng)語(yǔ)言代碼
cd +文件夾目錄
protoc 文件名.proto --swift_out="./“
protoc IMText.proto --swift_out="./“
3.用法:
//1.創(chuàng)建giftMsg
let giftMsg = GiftMessage.Builder()
giftMsg.giftname = giftname
giftMsg.giftUrl = giftURL
giftMsg.giftCount = giftCount
//2.獲取對(duì)應(yīng)的data
let giftData = (try! giftMsg.build()).data()
//3.發(fā)送禮物消息
sendMsg(data: giftData, type: 3)