Socket學習

一、 Socket介紹

來由:多個TCP連接或多個應用程序進程可能需要通過同一個TCP協(xié)議端口傳輸數(shù)據(jù)夸溶。為了區(qū)別不同的應用程序進程和連接缝裁,計算機操作系統(tǒng)為應用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口。應用層可以和傳輸層通過Socket接口氢妈,區(qū)分來自不同應用程序進程或網(wǎng)絡連接的通信段多,實現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務。

Socket又稱為“套接字”加缘,是系統(tǒng)提供的用于網(wǎng)絡通信的方法生百。Socket是對TCP/IP協(xié)議的封裝柄延,Socket本身并不是協(xié)議搜吧,而是一個調(diào)用接口(API),通過Socket摆昧,我們才能使用TCP/IP協(xié)議绅你。

建立Socket連接至少需要一對套接字昭躺,其中一個運行于客戶端领炫,稱為ClientSocket,另一個運行于服務器端似舵,稱為ServerSocket葱峡。套接字之間的連接過程分為三個步驟:服務器監(jiān)聽砰奕,客戶端請求泌参,連接確認常空。

Socket可以支持不同的傳輸層協(xié)議(TCP或UDP)漓糙,當使用TCP協(xié)議進行連接時,該Socket連接就是一個TCP連接,UDP連接同理蝗蛙。

2.png

二捡硅、Socket壮韭、TCP/IP和Http的聯(lián)系和區(qū)別

HTTP協(xié)議是基于TCP連接的纹因。
TCP/IP是傳輸層協(xié)議瞭恰,主要解決數(shù)據(jù)如何在網(wǎng)絡中傳輸惊畏;
而HTTP是應用層協(xié)議,主要解決如何包裝數(shù)據(jù)偷俭。

在傳輸數(shù)據(jù)時候可以只是用TCP/IP,但是這樣沒有應用層乳规,無法識別傳輸?shù)臄?shù)據(jù)類容合呐,這樣是沒有意義的淌实,如果想使傳輸?shù)臄?shù)據(jù)有意義,則必須使用應用層協(xié)議恨闪,HTTP就是一種咙咽,WEB使用它封裝HTTP文本信息,然后使用TCP/IP協(xié)議傳輸?shù)骄W(wǎng)絡上蜡豹。

Socket是應用層與TCP/IP協(xié)議族通信的中間軟件抽象層溉苛,是它的一組接口愚战。通過Socket凤巨,我們才能使用TCP/IP協(xié)議。

Socket和HTTP還有一個區(qū)別是Socket一旦建立連接佑淀,服務器可以主動將數(shù)據(jù)傳輸給客戶端彰檬;而HTTP則需要客戶端先向服務器發(fā)送請求之后才能將數(shù)據(jù)返回給客戶端逢倍。但實際上Socket建立之后因為種種原因较雕,會導致斷開連接,其中一個原因就是防火墻會斷開長時間處于非活躍狀態(tài)的連接扣典,因此需要輪詢高速網(wǎng)絡贮尖,這個連接是活躍的湿硝。

1.jpg

(附1:網(wǎng)絡七層協(xié)議由下往上分別為物理層关斜、數(shù)據(jù)鏈路層示括、網(wǎng)絡層、傳輸層蚤吹、會話層例诀、表示層和應用層。其中物理層裁着、數(shù)據(jù)鏈路層和網(wǎng)絡層通常被稱作媒體層繁涂,是網(wǎng)絡工程師所研究的對象;傳輸層二驰、會話層扔罪、表示層和應用層則被稱作主機層,是用戶所面向和關心的內(nèi)容桶雀。)
(附2:TCP/IP五層模型的協(xié)議分為:應用層矿酵、傳輸層、網(wǎng)絡層矗积、數(shù)據(jù)鏈路層和物理層)

12.png

三辜腺、Socket在iOS中的使用

  1. 第三方AsyncSockets的使用
#import <Foundation/Foundation.h>
#import "AsyncSocket.h"

enum{
    SocketOfflineByServer,
    SocketOfflineByUser,
};

@interface SocketSingleton : NSObject<AsyncSocketDelegate>

@property (nonatomic, strong) AsyncSocket    *socket;       // socket
@property (nonatomic, copy  ) NSString       *socketHost;   // socket的Host
@property (nonatomic, assign) UInt16         socketPort;    // socket的prot

@property (nonatomic, retain) NSTimer        *connectTimer; // 計時器

+ (SocketSingleton *)sharedInstance;

-(void)socketConnectHost;// socket連接

-(void)cutOffSocket;// 斷開socket連接

-(void)socketSendData:(NSData *) data;// socket發(fā)送數(shù)據(jù)

@end
#import "SocketSingleton.h"

@implementation SocketSingleton

+(SocketSingleton *) sharedInstance {
    static SocketSingleton *sharedInstace = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstace = [[self alloc] init];
    });
    return sharedInstace;
}

// socket連接
-(void)socketConnectHost {
    self.socket    = [[AsyncSocket alloc] initWithDelegate:self];
    NSError *error = nil;
    BOOL isConnect = [self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:-1 error:&error];;
    if (isConnect) {
        NSLog(@"socket連接成功");
    }else {
        NSLog(@"socket連接失敗");
    }
}

// socket發(fā)送數(shù)據(jù)
-(void)socketSendData:(NSData *) data {
    [self.socket writeData:data withTimeout:-1 tag:1];//-1不設置超時
}

// 連接成功回調(diào)
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
    NSLog(@"socket連接成功");
    [self.socket readDataWithTimeout: -1 tag: 0];
    self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];
    [self.connectTimer fire];
}

// 心跳連接
-(void)longConnectToSocket{
    // 根據(jù)服務器要求發(fā)送固定格式的數(shù)據(jù)呜投,假設為指令@"longConnect",但是一般不會是這么簡單的指令
    NSData   *dataStream  = [@"longConnect" dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:dataStream withTimeout:-1 tag:1];//-1不設置超時
}

-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *msg = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
    NSDictionary *dic = @{@"message":msg};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"SOCKETREAGSUCCESS" object:nil userInfo:dic];
    
    [self.socket readDataWithTimeout: -1 tag: 0];
}

-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag{
    // [self addMessage:[NSString stringWithFormat:@"發(fā)送了"]];
}

-(void)onSocketDidDisconnect:(AsyncSocket *)sock{
    NSLog(@"socket斷開連接 %ld",sock.userData);
    if (sock.userData == SocketOfflineByServer) {
        // 服務器掉線男图,重連
        [self socketConnectHost];
    }else if (sock.userData == SocketOfflineByUser) {
        // 如果由用戶斷開栈戳,不進行重連
        return;
    }
}

// 切斷socket
-(void)cutOffSocket{
    self.socket.userData = SocketOfflineByUser;
    [self.connectTimer invalidate];
    [self.socket disconnect];
}

@end
  1. 用C語言實現(xiàn)Socket

1褂痰、Socket調(diào)用庫函數(shù)主要有:

創(chuàng)建套接字 
Socket(af,type,protocol)

建立地址和套接字的聯(lián)系 
bind(sockid, local addr, addrlen)

服務器端偵聽客戶端的請求 
listen( Sockid ,quenlen)

建立服務器/客戶端的連接 (面向連接TCP) 
    客戶端請求連接 
    Connect(sockid, destaddr, addrlen)
    服務器端等待從編號為Sockid的Socket上接收客戶連接請求 
    newsockid=accept(Sockid谍憔,Clientaddr, paddrlen)

發(fā)送/接收數(shù)據(jù) 
    面向連接:     
    send(sockid, buff, bufflen) 
    面向無連接: 
    sendto(sockid,buff,…,addrlen) 
    recvfrom( )

釋放套接字      
close(sockid)

四、其他

iOS中Socket編程的方式:
BSD Socket:
BSD Socket 是UNIX系統(tǒng)中通用的網(wǎng)絡接口,它不僅支持各種不同的網(wǎng)絡類型,而且也是一種內(nèi)部進程之間的通信機制汗洒。而iOS系統(tǒng)其實本質(zhì)就是UNIX憨攒,所以可以用,但是比較復雜所刀。
CFSocket:
CFSocket是蘋果提供給我們的使用Socket的方式忧吟。
AsyncSocket:
第三方開源庫煌抒,首選方式绑青,也是在開發(fā)項目中經(jīng)常會用到的。
以后有機會慢慢學習。

參考文章:iOS學習之Socket使用簡明教程- AsyncSocket
項目地址: SocketDemo

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吕晌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖算灸,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贼涩,死亡現(xiàn)場離奇詭異占锯,居然都是意外死亡消略,警方通過查閱死者的電腦和手機晓殊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事墨技。” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵论衍,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么读宙? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任针肥,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘衬衬。我一直安慰自己奸远,他們只是感情好懒叛,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贡歧,像睡著了一般利朵。 火紅的嫁衣襯著肌膚如雪樟遣。 梳的紋絲不亂的頭發(fā)上屿衅,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天川梅,我揣著相機與錄音傀缩,去河邊找鬼。 笑死农猬,一個胖子當著我的面吹牛赡艰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斤葱,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼慷垮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了苦掘?” 一聲冷哼從身側響起换帜,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤楔壤,失蹤者是張志新(化名)和其女友劉穎鹤啡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹲嚣,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡递瑰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了隙畜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抖部。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖议惰,靈堂內(nèi)的尸體忽然破棺而出慎颗,到底是詐尸還是另有隱情,我是刑警寧澤言询,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布俯萎,位于F島的核電站,受9級特大地震影響运杭,放射性物質(zhì)發(fā)生泄漏夫啊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一辆憔、第九天 我趴在偏房一處隱蔽的房頂上張望撇眯。 院中可真熱鬧报嵌,春花似錦、人聲如沸熊榛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽来候。三九已至跷叉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間营搅,已是汗流浹背云挟。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留转质,地道東北人园欣。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像休蟹,于是被迫代替她去往敵國和親沸枯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

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