iOS網(wǎng)絡(luò)編程之Socket

1愿吹、套接字(socket)概念

套接字(socket)是通信的基石钳垮,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元吭练。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示冕茅,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址店茶,本地進(jìn)程的協(xié)議端口蝶棋,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口忽妒。

應(yīng)用層通過傳輸層進(jìn)行數(shù)據(jù)通信時(shí),TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問題兼贸。多個(gè)TCP連接或多個(gè)應(yīng)用程序進(jìn)程可能需要通過同一個(gè) TCP協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口在跳。應(yīng)用層可以和傳輸層通過Socket接口拧篮,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)螺垢。

簡單來說喧务,Socket更像是對傳輸層的簡單封裝赖歌,使的開發(fā)者可以更好的使用一些協(xié)議從而實(shí)現(xiàn)不用進(jìn)程和應(yīng)用之間的通訊。

以下是通訊示意圖

通訊示意圖

這里關(guān)于TCP/UDP協(xié)議不過多介紹功茴,TCP需要通過著名的三次握手進(jìn)行連接庐冯,不懂的朋友可以看看這篇文章->計(jì)算機(jī)網(wǎng)絡(luò)傳輸層知識(shí)點(diǎn)全覆蓋

2、iOS Socket應(yīng)用場景

Socket 使用長連接進(jìn)行通訊坎穿,凡是一個(gè)來回網(wǎng)絡(luò)請求解決不了問題的都會(huì)用socket展父。例如常見的IM類應(yīng)用、音視頻通話等玲昧。

與之對應(yīng)的是HTTP連接栖茉,HTTP連接使用的是“請求—響應(yīng)”的方式,不僅在請求時(shí)需要先建立連接孵延,而且需要客戶端向服務(wù)器發(fā)出請求后吕漂,服務(wù)器端才能回復(fù)數(shù)據(jù)。例如我們下載圖片尘应、瀏覽微信朋友圈等惶凝。

3、常用的socket類型

常用的Socket類型有兩種:流式Socket(SOCK_STREAM)和數(shù)據(jù)報(bào)式Socket(SOCK_DGRAM)菩收。

流式是一種面向連接的Socket梨睁,針對于面向連接的TCP服務(wù)應(yīng)用;
數(shù)據(jù)報(bào)式Socket是一種無連接的Socket娜饵,對應(yīng)于無連接的UDP服務(wù)應(yīng)用坡贺。

4、iOS使用的socket編程的方式有哪些?

第一種: BSD Socket

BSD Socket 是UNIX系統(tǒng)中通用的網(wǎng)絡(luò)接口箱舞,它不僅支持各種不同的網(wǎng)絡(luò)類型遍坟,而且也是一種內(nèi)部進(jìn)程之間的通信機(jī)制。而iOS系統(tǒng)其實(shí)本質(zhì)就是UNIX晴股,所以可以用愿伴,但是比較復(fù)雜。

第二種:CFSocket

CFSocket是蘋果提供給我們的使用Socket的方式电湘,但是用起來還是會(huì)不太順手隔节。當(dāng)然想使用的話,可以細(xì)細(xì)研究一下寂呛。

第三種:CocoaAsyncSocket

CocoaAsyncSocket是谷歌的開發(fā)者怎诫,基于BSD-Socket寫的一個(gè)IM框架,它給Mac和iOS提供了易于使用的贷痪、強(qiáng)大的異步套接字庫幻妓,向上封裝出簡單易用OC接口。省去了我們面向Socket以及數(shù)據(jù)流Stream等繁瑣復(fù)雜的編程劫拢。

5肉津、使用CocoaAsyncSocket

首先點(diǎn)擊上面的鏈接下載CocoaAsyncSocket的源碼强胰,把以下文件拷貝到自己的項(xiàng)目中:


CocoaAsyncSocket開發(fā)使用的文件

我們這里只是簡單講解GCDAsyncSocket的使用,它主要用于開發(fā)TCP的連接妹沙。由于TCP是長連接偶洋,我們需要在自己的項(xiàng)目中使GCDAsyncSocket保持全局唯一性,所以我們在項(xiàng)目里聲明一個(gè)單例類 AsyncSocketManager以下是AsyncSocketManager.h的結(jié)構(gòu)

@interface AsyncSocketManager : NSObject<GCDAsyncSocketDelegate>
+(AsyncSocketManager *)shareAsyncSocket;


@property (nonatomic,strong) GCDAsyncSocket *asyncSocket;
@property (nonatomic,copy) NSString *socketHost;//注意是ip地址初烘,并不是DNS域名
@property (nonatomic,assign) UInt16 socketPort;
@property (nonatomic,strong) NSTimer *connectTimer;

-(void)socketConnectHost;//連接socket
-(void)cutoffSocket;//斷開socket


@end
5.1 Socket的初始化連接
-(void)socketConnectHost{
    //創(chuàng)建socket并指定代理對象為self,代理隊(duì)列必須為主隊(duì)列
    self.asyncSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    NSError *error;
    [self.asyncSocket connectToHost:self.socketHost onPort:self.socketPort error:&error];
}

連接成功的代理方法

//連接成功的回調(diào)
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    [self addTimer];// 連接成功開啟定時(shí)器
    [self.asyncSocket readDataWithTimeout:- 1 tag:0];// 連接后,可讀取服務(wù)端的數(shù)據(jù)
}

讀取數(shù)據(jù)成功后的代理涡真,連接成功之后需要開啟一個(gè)定時(shí)器規(guī)定一定的時(shí)間后需要給服務(wù)器發(fā)送心跳包,用于檢測是否服務(wù)器在線

// 添加定時(shí)器
- (void)addTimer
{
    // 長連接定時(shí)器
    self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
    // 把定時(shí)器添加到當(dāng)前運(yùn)行循環(huán),并且調(diào)為通用模式
    [[NSRunLoop currentRunLoop] addTimer:self.connectTimer forMode:NSRunLoopCommonModes];
}

/** 注意:
    心跳連接中發(fā)送給服務(wù)端的數(shù)據(jù)只是作為測試代碼,根據(jù)你們公司需求,
    或者和后臺(tái)商定好心跳包的數(shù)據(jù)以及發(fā)送心跳的時(shí)間間隔.
    服務(wù)端也需要有對應(yīng)的心跳檢測,以此檢測客戶端是否在線.
 */
-(void)longConnectToSocket{
    NSLog(@"我發(fā)送了一次心跳包");
    NSString *longConnect = @"longConnect";//需要和服務(wù)器商量好
    NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
    
    [self.asyncSocket writeData:dataStream withTimeout:1 tag:1];
}
/**
 讀取數(shù)據(jù)成功的回調(diào)
 @param sock 客戶端socket
 @param data 讀取到的數(shù)據(jù)
 @param tag 本次讀取的標(biāo)記
 */
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    NSString *text = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"讀取的數(shù)據(jù)==%@",text);
    // 讀取到服務(wù)端數(shù)據(jù)值后,能再次讀取
    [self.asyncSocket readDataWithTimeout:- 1 tag:0];//這里還需要進(jìn)行讀取操作肾筐,否則只能讀取一次
}
5.2 斷開連接

sokect斷開連接時(shí),需要清空代理和客戶端本身的socket.

[self.asyncSocket disconnect];//斷開連接

/**
 客戶端socket斷開后的回調(diào)
 @param sock 客戶端socket
 @param err 錯(cuò)誤描述
 */
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    self.asyncSocket.delegate = nil;
    self.asyncSocket = nil;
    [self.connectTimer invalidate];
}
6哆料、總結(jié)

CocoaAsyncSocket 是前人幫我們封裝好的Socket,如果你想了解的更深的話也可以去了解Apple提供的BSD Socket吗铐、CFSocket等接口东亦。

Socket都是用于應(yīng)用之間進(jìn)行與服務(wù)器之間需要長時(shí)間的連接,需要時(shí)刻的保持連接唬渗,已到達(dá)數(shù)據(jù)時(shí)效性典阵。比較常用的就是IM類的應(yīng)用,不過每一個(gè)IM類的應(yīng)用企業(yè)都是自己封裝的Socket以適應(yīng)自己公司的不同業(yè)務(wù)功能需求镊逝。

雖然市面上有非常多的各種各樣的Socket框架可以用壮啊,但我認(rèn)為作為一名開發(fā)者,我們有責(zé)任去搞懂Socket通訊的原理撑蒜,至少是需要了解歹啼。

好了,這篇文章就到這里啦~~~
我最近在逼著自己寫文章座菠,以前總是認(rèn)為像這樣的文章網(wǎng)上到處都是而且有一些大神寫的非常好狸眼,so,我干嘛要寫呢……不過最后想想還是認(rèn)為有必要自己記錄下來浴滴,別人的永遠(yuǎn)是別人的拓萌,只有自己消化了,理解了升略,那才能是你自己的東西微王!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市品嚣,隨后出現(xiàn)的幾起案子骂远,更是在濱河造成了極大的恐慌,老刑警劉巖腰根,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拓型,居然都是意外死亡额嘿,警方通過查閱死者的電腦和手機(jī)瘸恼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來册养,“玉大人东帅,你說我怎么就攤上這事∏蚶梗” “怎么了靠闭?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坎炼。 經(jīng)常有香客問我愧膀,道長,這世上最難降的妖魔是什么谣光? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任檩淋,我火速辦了婚禮,結(jié)果婚禮上萄金,老公的妹妹穿的比我還像新娘蟀悦。我一直安慰自己,他們只是感情好氧敢,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布日戈。 她就那樣靜靜地躺著,像睡著了一般孙乖。 火紅的嫁衣襯著肌膚如雪浙炼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天的圆,我揣著相機(jī)與錄音鼓拧,去河邊找鬼。 笑死越妈,一個(gè)胖子當(dāng)著我的面吹牛季俩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梅掠,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼酌住,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阎抒?” 一聲冷哼從身側(cè)響起酪我,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎且叁,沒想到半個(gè)月后都哭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年欺矫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纱新。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,926評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡穆趴,死狀恐怖脸爱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情未妹,我是刑警寧澤簿废,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站络它,受9級特大地震影響族檬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酪耕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一导梆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迂烁,春花似錦看尼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至却盘,卻和暖如春狰域,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黄橘。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工兆览, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塞关。 一個(gè)月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓抬探,卻偏偏與公主長得像,于是被迫代替她去往敵國和親帆赢。 傳聞我的和親對象是個(gè)殘疾皇子小压,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 一.iOS網(wǎng)絡(luò)編程層次模型 在前文《深入淺出的Cocoa之Bonjour網(wǎng)絡(luò)編程》中我介紹了如何在Mac系統(tǒng)下進(jìn)行...
    maTianHong閱讀 489評論 1 1
  • 一: 網(wǎng)絡(luò)各個(gè)協(xié)議:TCP/IP、SOCKET椰于、HTTP 網(wǎng)絡(luò)七層由下往上分別為物理層怠益、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層瘾婿、傳輸層...
    iYeso閱讀 1,439評論 0 13
  • 在了解socket網(wǎng)絡(luò)編程之前蜻牢,我們需要先知道以下幾個(gè)問題: 網(wǎng)絡(luò)中進(jìn)程之間如何通信烤咧?Socket是什么?TCP和...
    追風(fēng)箏的熒火蟲閱讀 1,257評論 0 17
  • 在了解socket網(wǎng)絡(luò)編程之前孩饼,我們需要先知道以下幾個(gè)問題: 網(wǎng)絡(luò)中進(jìn)程之間如何通信髓削? Socket是什么? TC...
    心至靜行至遠(yuǎn)閱讀 7,526評論 12 87
  • 城市早已沉睡在甜美的虛偽真實(shí)就像刺眼的陽光習(xí)慣伸手就檔我像火燒在大雨下剩最后微弱的火花看不見國王的新衣裳是否太倔強(qiáng)...
    gxwang閱讀 1,904評論 0 0