iOS學習之Socket,iossocket
Socket在百度百科的定義
網路上的兩個程式通過一個雙向的通訊串連實現資料的交換,這個串連的一端稱為一個socket。
相關的描述
Socket的英文原義是“孔”或“插座”。作為BSD UNIX的進程通訊機制,取後一種意思。通常也稱作"通訊端",用於描述IP地址和連接埠,是一個通訊鏈的控制代碼,可以用來實現不同虛擬機器或不同電腦之間的通訊。
在Internet上的主機一 般運行了多個服務軟體,同時提供幾種服務。每種服務都開啟一個Socket,並綁定到一個連接埠上,不同的連接埠對應於不同的服務。
Socket正如其英文原意那樣,像一個多孔插座。一台主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟體將插頭插到不同編號的插座,就可以得到不同的服務。
正如上述的介紹Socket一定包含了通訊的雙發,即用戶端(Client)與服務端(server)。
伺服器利用Socket監聽連接埠
用戶端發起串連
服務端返回資訊,建立串連,開始通訊
用戶端,服務端中斷連線
Socket 第三方 GCDAsyncSocket 的:https://github.com/AlonerOwl/socket
一、伺服器端:
在伺服器端構建的時候,我們需要匯入第三方架構和其他的一些C語言套件
#import "GCDAsyncSocket.h"#include <arpa/inet.h>#include <net/if.h>#include <ifaddrs.h>
1、聲明一個 socket 並進行初始化 socket
/// 伺服器端socket,決定不能使用局部變數,不能被銷毀@property (nonatomic, strong) GCDAsyncSocket *socket;// 初始化socketself.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
2、綁定連接埠,監聽串連訊息
連接埠號碼設定:連接埠號碼大於1024,不能使用市面上已經被佔用的斷開 eg.8080,8800,因此在綁定時,要進行一個安全判斷。
NSError *error; // 綁定連接埠,監聽串連訊息 BOOL result = [self.socket acceptOnPort:[self.portTextField intValue] error:&error];
3、監聽用戶端,擷取新的socket串連之後調用以下方法,並進行一些邏輯處理
// 參數1:當前伺服器的socket// 參數2:接收到的用戶端的新socket- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket;
4、讀取訊息
讀取方法是哪個socket調用就讀取哪個socket的攜帶訊息(對應的是用戶端發送訊息)
// -1 不限定讀取時間,tag為一個標記值 [newSocket readDataWithTimeout:-1 tag:0];
5、寫資料
寫給誰就用誰來調用
// string 變數就是我們要寫入的訊息,它需要轉為Data// -1 和讀取訊息時的意思一樣,表示不限定時間// tag 為標記值,一般置為0[newSocket writeData:[string dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
6、讀取到 socket 的訊息,在 readDataWithTimeout 後執行
主要用於對接收到訊息的處理和將訊息轉寄給另一個接收的用戶端,這樣就起到兩個用戶端的通訊,具體資料格式和邏輯根據個人需求自行處理。以下方法和readDataWithTimeout 方法配套執行,只要有 readDataWithTimeout 方法,就會有下面的方法
// 參數1:伺服器的socket // 參數2:伺服器讀取的資料// 參數3:標記- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
7、關閉伺服器
將伺服器的 socket 中斷連線後置為nil
#pragma mark - 關閉服務- (IBAction)stopService:(NSButton *)sender{ if (self.socket) {#warning 關閉 [self.socket disconnect]; self.socket = nil; [self addInfoString:@"關閉服務"]; } else { [self addInfoString:@"已經關閉,無需重複"]; }}
8、監聽串連的斷開
當伺服器中斷連線後調用,主要用於處理socket儲存列表。
// 已經中斷連線時調用,監聽串連的斷開,並且處理socket儲存列表- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{// [self addInfoString:[NSString stringWithFormat:@"已經中斷連線 %@", err]]; [self addInfoString:[NSString stringWithFormat:@"已經中斷連線"]]; if ([self.clients allKeysForObject:sock].count > 0) { // 當用戶端斷開時,進行一些刪除socket的操作 [self.clients removeObjectForKey:[self.clients allKeysForObject:sock][0]]; NSLog(@"%@", self.clients); } else { // 當伺服器socket斷開時,處理用戶端socket列表 [self.clients removeAllObjects]; NSLog(@"%@", self.clients); }}
二、用戶端
在構建客戶器端的時候,需要匯入第三方的類
#import "GCDAsyncSocket.h"
1、聲明和初始化用戶端socket(和伺服器端類似)
@interface ViewController () <GCDAsyncSocketDelegate>{ // client端socket GCDAsyncSocket *_clientSocket;}@end_clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
2、串連伺服器
// 參數1:伺服器的IP地址 // 參數2:伺服器的連接埠號碼(伺服器綁定的連接埠號碼)// 參數3:錯誤資訊- (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr
3、串連到伺服器後執行的代理方法
主要用於從伺服器中讀取資料
// 串連到伺服器- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{ NSLog(@"串連到伺服器"); _serverSocket = sock; // 讀資料 [_serverSocket readDataWithTimeout:-1 tag:0];}
4、讀到伺服器反饋的資料
方法和伺服器第6步的方法一樣,對伺服器反饋的資料進行處理和利用
5、讀寫訊息的方法後伺服器端是一樣的,在這裡我就不再重複介紹了,大家可以參照伺服器的讀寫訊息的方法
三、下面是自己學習的一個簡易版的Demo,有興趣的朋友可以下載看看
:https://github.com/AlonerOwl/Socket-