ios socket即時(shí)通訊

首先理一下網(wǎng)絡(luò)通訊三要素

  1. IP地址(主機(jī)名)
  • 網(wǎng)絡(luò)設(shè)備標(biāo)示
  • 本地回環(huán)地址:127.0.0.1 主機(jī)名:localHost
  1. 端口號(hào)
  • 用于標(biāo)識(shí)進(jìn)程的邏輯地址鸥滨,不同進(jìn)程的標(biāo)示
  • 有效端口:0 ~ 65535
  • 其中 0 ~ 1024 由系統(tǒng)使用或者保留端口
  1. 傳輸協(xié)議(通訊的規(guī)則)
  • TCP
  • UDP

1.Socket到底是什么東西烦感?以下這幅流程圖表示運(yùn)行過(guò)程

屏幕快照 2018-07-10 下午5.43.01.png

總結(jié):socket其實(shí)就是:用來(lái)操作某個(gè)IP上的某個(gè)端口來(lái)達(dá)到點(diǎn)對(duì)點(diǎn)通訊效果丛忆,本身就是一個(gè)抽象的東東鲁猩,通訊就是通過(guò)socket來(lái)交互,可以面向TCP和UDP兩種連接

  • TCP 采用三次握手來(lái)創(chuàng)建連接,是可靠連接,是長(zhǎng)連接
    分手是四次分手雏婶,客戶端向服務(wù)器發(fā)送分手,會(huì)經(jīng)過(guò)兩次分手白指;服務(wù)器端向客戶端發(fā)送分手留晚,也會(huì)經(jīng)過(guò)兩次分手

  • UDP 是不可靠連接,發(fā)送的東西是不管到達(dá)的

2.Socket終端使用案例:

  1. 新建兩個(gè)終端控制臺(tái)
  2. 第一臺(tái)輸入命令: nc -l 6969 (開(kāi)啟nc命令告嘲,使用6969端口倔丈,充當(dāng)服務(wù)器端)
  3. 第二臺(tái)輸入命令:nc 127.0.0.1 6969 (兩臺(tái)的端口保持一致,充當(dāng)客戶端)
  4. 最后兩臺(tái)終端就可以實(shí)現(xiàn)通訊了状蜗,可以相互發(fā)送消息

以上案列采用的 “nc”命令,可以用來(lái)檢測(cè)本地GCP連接

3.Socket 代碼實(shí)際運(yùn)用

socket是成雙成對(duì)的出現(xiàn)

  1. 導(dǎo)入框架
#import <sys/socket.h>
#import <arpa/inet.h>
#import <netinet/in.h>
  1. 定義端口號(hào)和ip
static const char *serve_ip = "127.0.0.1";  //ip
static const short serve_port = 6969;    //port

3.定義socket

@property (nonatomic,assign) int clientSockt; //定義socket
/**  */
@property (nonatomic,strong) UITextField *msgTextFiled; //創(chuàng)建消息文本
/**  */
@property (nonatomic,strong) NSThread *thread;
  1. 創(chuàng)建socket , 連接服務(wù)器端
//創(chuàng)建socket
-(void)initSockt{
    /**
     參數(shù)
     domain : 協(xié)議域 ,AF_INET ->IPV4
     type: Socket 類型,SOCK_STREAM(流/TCP)/SOCK_DGRAM(報(bào)文/UDP)
     protocol: IPPROTO_TCP(如果寫(xiě)0鹉动,那么就會(huì)自動(dòng)選擇)
     
     返回值
     socket
     */
    _clientSockt = socket(AF_INET, SOCK_STREAM, 0);
 
    
    
    //連接IP地址和服務(wù)端
    struct sockaddr_in serverAddr;
    //賦值長(zhǎng)度
    serverAddr.sin_len = sizeof(serverAddr);
    
    serverAddr.sin_family = AF_INET;
    
    //IP地址
    inet_aton(serve_ip, &serverAddr.sin_addr);
    
    //端口號(hào)
    serverAddr.sin_port = htons(serve_port);
    
    int connetResult = connect(_clientSockt,(const struct sockaddr *)&serverAddr, sizeof(serverAddr));
    if (connetResult == 0) {
        NSLog(@"連接成功");
        //開(kāi)啟一個(gè)線程模擬
        self.thread = [[NSThread alloc]initWithTarget:self selector:@selector(receveAction) object:nil];
        [self.thread start];
    }
    else{
        NSLog(@"連接失敗 %d",connetResult);
        return;
    }
}
  1. 接收消息
-(void)receveAction{
    /**
     參數(shù)
     1.客戶端socket
     2.接受內(nèi)容緩沖區(qū)地址
     3.接受內(nèi)容緩存區(qū)長(zhǎng)度
     4.接受方式轧坎,0表示阻塞,必須等待服務(wù)器返回?cái)?shù)據(jù)
     
     返回值
     如果超過(guò)泽示,則返回讀入的字節(jié)數(shù)缸血,失敗則返回SOCKET_ERROR
     */
  while (1) {
        uint8_t buffer[1024];//空間,準(zhǔn)備數(shù)據(jù)
        
        size_t recvlen = recv(_clientSockt, buffer, sizeof(buffer), 0);//等待著獲的數(shù)據(jù)
        NSLog(@"接受到多少數(shù)據(jù)%ld",recvlen);
        //解析數(shù)據(jù)(獲取到的服務(wù)器數(shù)據(jù))
        NSData *date = [NSData dataWithBytes:buffer length:recvlen];
        NSString *str  = [[NSString alloc]initWithData:date encoding:NSUTF8StringEncoding];
        NSLog(@"接收到的內(nèi)容:%@",str);
    }
}
  1. 接下來(lái)械筛,我們來(lái)利用終端來(lái)模擬服務(wù)器捎泻,向我們的app發(fā)送消息,上面我們已經(jīng)說(shuō)過(guò),怎么使用終端來(lái)建立一個(gè)服務(wù)器端口埋哟,建立連接笆豁。好了,這個(gè)時(shí)候赤赊,把我們的App跑起來(lái)吧闯狱,看看有什么神奇的效果
    在終端輸入:
nc -l 6969 //這是建立服務(wù)器端口,再把APP跑起來(lái)抛计,這時(shí)應(yīng)該就會(huì)發(fā)現(xiàn)控制臺(tái)打印“連接成功”哄孤。這時(shí),就可以任意發(fā)送消息了
123456 //這是發(fā)送的消息
1213131SAS //這是發(fā)送的消息

這時(shí)吹截,在app控制臺(tái)打印出效果

2018-07-12 11:26:12.459423+0800 Socket[1232:116451] 連接成功
2018-07-12 11:26:23.504420+0800 Socket[1232:116570] 接受到多少數(shù)據(jù)7
2018-07-12 11:26:23.504659+0800 Socket[1232:116570] 接收到的內(nèi)容:123456

2018-07-12 11:26:26.944561+0800 Socket[1232:116570] 接受到多少數(shù)據(jù)11
2018-07-12 11:26:26.944768+0800 Socket[1232:116570] 接收到的內(nèi)容:1213131SAS

ok,一切盡在不言中

  1. 接受消息瘦陈,我們這邊已經(jīng)搞定,那么接下來(lái)我們?cè)賮?lái)搞定發(fā)送消息

首先創(chuàng)建一個(gè)按鈕波俄、一個(gè)輸入文本框晨逝,點(diǎn)擊按鈕,發(fā)送文本框內(nèi)的字符串弟断,調(diào)用以下方法咏花,實(shí)現(xiàn)發(fā)送

-(void)sendAction:(NSString *)msg{
    //3.發(fā)送數(shù)據(jù)
    /**
     參數(shù)
     1.客戶端socket
     2.發(fā)送內(nèi)容地址(指針)
     3.發(fā)送內(nèi)容長(zhǎng)度
     4.發(fā)送內(nèi)容標(biāo)志,一般為0
     
     返回值
     如果成功,則返回發(fā)送的字節(jié)數(shù)昏翰,失敗則返回SOCKET_ERROR
     
     */
    //void * 表示萬(wàn)能指針(以下兩種都可以)
    //    NSString *msg = @"hello";
    //    const char * msg = @"hello";
    ssize_t sendLen = send(_clientSockt, msg.UTF8String, strlen(msg.UTF8String), 0);
    NSLog(@"發(fā)送了 %ld字節(jié)",sendLen);
    
}

發(fā)送成功后苍匆,這時(shí)在終端上就顯示出了,剛剛發(fā)送的消息

  1. 正所謂棚菊,有始就有終浸踩,我們還剩下最后一步,那就是斷開(kāi)連接统求,如果不用了检碗,就得把鏈接斷開(kāi),節(jié)約資源
-(void)disConnection{
    //關(guān)閉數(shù)據(jù)連接
    [self.thread cancel];
    close(_clientSockt);
}

4. socket 實(shí)際運(yùn)用

是實(shí)際開(kāi)發(fā)過(guò)程中码邻,對(duì)于一般的小型聊天折剃,都采用“環(huán)信、融云像屋、LeanClould”,但是對(duì)于主供消息聊天的就不可能采用這些三方公司的怕犁,因?yàn)閮r(jià)錢(qián)太高,所以就會(huì)引用一些三方框架:

  1. 基本socket 原生己莺, CocoaAsyncSocket
  • 就是BSD Socket奏甫,處理了很多協(xié)議
  • 是基于傳輸層封裝的一套框架
  1. 基于WebSocket , SocketRocket,SRWebSocket
  • 用于瀏覽器的長(zhǎng)連接協(xié)議
  1. 基于MQIT, MQTTKit 凌受、MQTTClient
  • 適用訂閱的消息機(jī)制,列如:滴滴打車(chē)地圖上的小車(chē)軌跡
  • 適用于物聯(lián)網(wǎng)阵子,傳輸層更小,低帶寬胜蛉,性能更優(yōu)
  • 位于應(yīng)用層的聊天協(xié)議
  1. 基于XMPP,XMPPFrameWork
  • 缺點(diǎn)挠进,是基于XML的數(shù)據(jù)來(lái)傳輸?shù)?/li>
  • 位于應(yīng)用層的聊天協(xié)議
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腾么,隨后出現(xiàn)的幾起案子奈梳,更是在濱河造成了極大的恐慌,老刑警劉巖解虱,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攘须,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡殴泰,警方通過(guò)查閱死者的電腦和手機(jī)于宙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)悍汛,“玉大人捞魁,你說(shuō)我怎么就攤上這事±敫溃” “怎么了谱俭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵奉件,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我昆著,道長(zhǎng)县貌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任凑懂,我火速辦了婚禮煤痕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘接谨。我一直安慰自己摆碉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布脓豪。 她就那樣靜靜地躺著巷帝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扫夜。 梳的紋絲不亂的頭發(fā)上锅睛,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音历谍,去河邊找鬼。 笑死辣垒,一個(gè)胖子當(dāng)著我的面吹牛望侈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勋桶,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脱衙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了例驹?” 一聲冷哼從身側(cè)響起捐韩,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鹃锈,沒(méi)想到半個(gè)月后荤胁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屎债,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年仅政,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盆驹。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡圆丹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躯喇,到底是詐尸還是另有隱情辫封,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站倦微,受9級(jí)特大地震影響妻味,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜璃诀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一弧可、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劣欢,春花似錦棕诵、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至牧抵,卻和暖如春笛匙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背犀变。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工妹孙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人获枝。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓蠢正,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親省店。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嚣崭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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