用socket可以完成像QQ那樣發送即時新聞的功效。客戶端和辦事端須要樹立長銜接,在長銜接的情形下,發送新聞。客戶端可以發送心跳包來檢測長銜接。
在IOS開辟中應用socket,普通都是用第三方庫AsyncSocket,不能不認可這個庫確切很壯大。下載地址CocoaAsyncSocket
。
特征
AsyncSocket類是支撐TCP的。
AsyncUdpSocket是支撐UDP的。
AsyncSocket是封裝了CFSocket和CFSteam的TCP/IP socket收集庫。它供給了異步操作,當地cocoa類的基於delegate的完全支撐。重要有以下特征:
AsyncUdpSocket是UDP/IP socket收集庫,包裝自CFSocket。它的任務很像TCP版本,只不外是用於處置UDP的。它包含基於非壅塞隊列的發送吸收操作,完全的拜托支撐,基於runloop,自包括的類,和支撐IPV4和IPV6。
應用AsyncSocket的時刻可以做一層封裝,依據需求供給幾個接口出來。好比:銜接、斷開銜接、發送新聞等等。還有接收新聞,接收到的新聞可以經由過程告訴、署理、block等傳出去。
上面簡略引見一下對AsyncSocket應用.普通來講,一個用戶只須要樹立一個socket長銜接,所以可以用單例類便利應用。
界說單列類:LGSocketServe
LGSocketServe.h
//
// LGSocketServe.h
// AsyncSocketDemo
//
#import <Foundation/Foundation.h>
#import "AsyncSocket.h"
@interface LGSocketServe : NSObject<AsyncSocketDelegate>
+ (LGSocketServe *)sharedSocketServe;
@end
LGSocketServe.m
//
// LGSocketServe.m
// AsyncSocketDemo
//
#import "LGSocketServe.h"
@implementation LGSocketServe
static LGSocketServe *socketServe = nil;
#pragma mark public static methods
+ (LGSocketServe *)sharedSocketServe {
@synchronized(self) {
if(socketServe == nil) {
socketServe = [[[self class] alloc] init];
}
}
return socketServe;
}
+(id)allocWithZone:(NSZone *)zone
{
@synchronized(self)
{
if (socketServe == nil)
{
socketServe = [super allocWithZone:zone];
return socketServe;
}
}
return nil;
}
@end
樹立socket長銜接
LGSocketServe.h
@property (nonatomic, strong) AsyncSocket *socket; // socket
// socket銜接
- (void)startConnectSocket;
LGSocketServe.m
//本身設定
#define HOST @"192.168.0.1"
#define PORT 8080
//設置銜接超時
#define TIME_OUT 20
- (void)startConnectSocket
{
self.socket = [[AsyncSocket alloc] initWithDelegate:self];
[self.socket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
if ( ![self SocketOpen:HOST port:PORT] )
{
}
}
- (NSInteger)SocketOpen:(NSString*)addr port:(NSInteger)port
{
if (![self.socket isConnected])
{
NSError *error = nil;
[self.socket connectToHost:addr onPort:port withTimeout:TIME_OUT error:&error];
}
return 0;
}
宏界說一下HOST、PORT、TIME_OUT,完成startConnectSocket辦法。這個時刻要設置一下AsyncSocket的署理AsyncSocketDelegate。當長銜接勝利以後會挪用:
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
//這是異步前往的銜接勝利,
NSLog(@"didConnectToHost");
}
心跳
LGSocketServe.h
@property (nonatomic, retain) NSTimer *heartTimer; // 心跳計時器
LGSocketServe.m
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
//這是異步前往的銜接勝利,
NSLog(@"didConnectToHost");
//經由過程准時器赓續發送新聞,來檢測長銜接
self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
[self.heartTimer fire];
}
// 心跳銜接
-(void)checkLongConnectByServe{
// 向辦事器發送固定可是的新聞,來檢測長銜接
NSString *longConnect = @"connect is here";
NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:data withTimeout:1 tag:1];
}
在銜接勝利的回調辦法裡,啟動准時器,每隔2秒向辦事器發送固定的新聞來檢測長銜接。(這個依據辦事器的須要便可以了)
斷開銜接
1,用戶手動斷開銜接
LGSocketServe.h
// 斷開socket銜接
-(void)cutOffSocket;
LGSocketServe.m
-(void)cutOffSocket
{
self.socket.userData = SocketOfflineByUser;
[self.socket disconnect];
}
cutOffSocket是用戶斷開銜接以後,不在測驗考試從新銜接。
2,wifi斷開,socket斷開銜接
LGSocketServe.m
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);
if (err.code == 57) {
self.socket.userData = SocketOfflineByWifiCut;
}
}
wifi斷開以後,會回調onSocket:willDisconnectWithError:辦法,err.code == 57,這個時刻設置self.socket.userData = SocketOfflineByWifiCut。
從新銜接
socket斷開以後會回調:
LGSocketServe.m
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{
NSLog(@"7878 sorry the connect is failure %ld",sock.userData);
if (sock.userData == SocketOfflineByServer) {
// 辦事器失落線,重連
[self startConnectSocket];
}
else if (sock.userData == SocketOfflineByUser) {
// 假如由用戶斷開,不停止重連
return;
}else if (sock.userData == SocketOfflineByWifiCut) {
// wifi斷開,不停止重連
return;
}
}
在onSocketDidDisconnect回調辦法外面,會依據self.socket.userData來斷定能否須要從新銜接。
發送新聞
LGSocketServe.h
// 發送新聞
- (void)sendMessage:(id)message;
LGSocketServe.m
//設置寫入超時 -1 表現不會應用超時
#define WRITE_TIME_OUT -1
- (void)sendMessage:(id)message
{
//像辦事器發送數據
NSData *cmdData = [message dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:cmdData withTimeout:WRITE_TIME_OUT tag:1];
}
//發送新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithtag:(long)tag
{
}
發送新聞勝利以後會挪用onSocket:didWriteDataWithtag:,在這個辦法裡可以停止讀撤消息。
接收新聞
LGSocketServe.m
//設置讀取超時 -1 表現不會應用超時
#define READ_TIME_OUT -1
#define MAX_BUFFER 1024
//發送新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithtag:(long)tag
{
//讀撤消息
[self.socket readDataWithTimeout:-1 buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
}
//接收新聞勝利以後回調
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//辦事端前往新聞數據量比擬年夜時,能夠分屢次前往。所以在讀撤消息的時刻,設置MAX_BUFFER表現每次最多讀取若干,當data.length < MAX_BUFFER我們以為有能夠是接收完一個完全的新聞,然後才解析
if( data.length < MAX_BUFFER )
{
//收到成果解析...
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dic);
//解析出來的新聞,可以經由過程告訴、署理、block等傳出去
}
[self.socket readDataWithTimeout:READ_TIME_OUT buffer:nil bufferOffset:0 maxLength:MAX_BUFFER tag:0];
接收新聞後去解析,然後可以經由過程告訴、署理、block等傳出去。在onSocket:didReadData:withTag:回調辦法外面須要赓續讀撤消息,由於數據量比擬年夜的話,辦事器會分屢次前往。所以我們須要界說一個MAX_BUFFER的宏,表現每次最多讀取若干。當data.length < MAX_BUFFER我們以為有能夠是接收完一個完全的新聞,然後才解析 。
失足處置
LGSocketServe.m
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
NSData * unreadData = [sock unreadData]; // ** This gets the current buffer
if(unreadData.length > 0) {
[self onSocket:sock didReadData:unreadData withTag:0]; // ** Return as much data that could be collected
} else {
NSLog(@" willDisconnectWithError %ld err = %@",sock.userData,[err description]);
if (err.code == 57) {
self.socket.userData = SocketOfflineByWifiCut;
}
}
}
socket失足會回調onSocket:willDisconnectWithError:辦法,可以經由過程unreadData來讀取將來得及讀取的buffer。
應用
導入#import “LGSocketServe.h”
LGSocketServe *socketServe = [LGSocketServe sharedSocketServe];
//socket銜接前先斷開銜接以避免之前socket銜接沒有斷勸導致閃退
[socketServe cutOffSocket];
socketServe.socket.userData = SocketOfflineByServer;
[socketServe startConnectSocket];
//發送新聞 @"hello world"只是舉個列子,詳細依據辦事真個新聞格局
[socketServe sendMessage:@"hello world"];
【iOS運用中應用AsyncSocket庫處置Socket通訊的用法講授】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!