服務(wù)端
@property (nonatomic, strong) GCDAsyncSocket *serverSocket; //服務(wù)端socket
@property (nonatomic, strong) GCDAsyncSocket *clientSocket;//客戶端連接過來的socket
//創(chuàng)建服務(wù)端并啟動(dòng)服務(wù)
- (void)createLocalServer {
if (self.serverSocket == nil) {
self.serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
}
NSError *error = nil;
BOOL isa = [self.serverSocket acceptOnPort:[SocketServerPort integerValue] error:&error];
NSLog(@"----%d----",isa);
}
#pragma mark - 代理方法(GCDAsyncSocketDelegate)
//連接成功
- (void)socket:(GCDAsyncSocket *)sender didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
self.clientSocket = newSocket; //接收客戶端連接過來的socket對(duì)象
self.clientSocket.delegate = self;//設(shè)置代理
//讀取數(shù)據(jù),以CRLFData結(jié)尾即表示是一條數(shù)據(jù)(以此來斷開多個(gè)包一起發(fā)過來的粘包問題)
[self.clientSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
}
//斷開連接或連接失敗
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"-Socket斷開連接--err = %@ --- code = %ld",err.localizedDescription,(long)err.code);
}
//讀取數(shù)據(jù)
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
//接收到的消息處理
NSData *newData = [data subdataWithRange:NSMakeRange(0, data.length-2)];
//先嘗試轉(zhuǎn)字典
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:newData options:kNilOptions error:nil];
if (result) {
//處理獲取到的字典數(shù)據(jù)
}
} else {
//如果字典轉(zhuǎn)換失敗,則嘗試轉(zhuǎn)換字符串
NSString *content = [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
NSLog(@"--接收到的消息-- content = %@",content);
//接收到的字符串處理
}
//持續(xù)接收數(shù)據(jù) 以CRLFData結(jié)尾即表示是一條數(shù)據(jù)(以此來斷開多個(gè)包一起發(fā)過來的粘包問題)
//如果不在讀取完以后寫這個(gè)方法,那就只讀取一次數(shù)據(jù),不會(huì)持續(xù)讀取
[self.clientSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
}
#pragma mark - 寫數(shù)據(jù)成功回調(diào)
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(@"------發(fā)送完成---------");
}
#pragma mark - 發(fā)送數(shù)據(jù)
//發(fā)送文本類型消息
- (void)sendTextMessage:(NSString *)text {
if (text.length == 0 || text == nil) {
return;
}
if (!_clientSocket) {
NSLog(@"socket未連接");
return;
}
NSLog(@"發(fā)送的數(shù)據(jù)---(%@)",text);
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *printData = [[NSMutableData alloc] initWithData:data];
//拼接結(jié)束符
[printData appendData:[GCDAsyncSocket CRLFData]];
// withTimeout -1 : 無窮大,一直等
[self.clientSocket writeData:printData withTimeout:-1 tag:0];
}
//發(fā)送字典數(shù)據(jù)
- (void)sendTextMessageWithDict:(NSDictionary *)dict {
if (dict == nil || dict.count == 0) {
return;
}
if (!_clientSocket) {
NSLog(@"socket未連接");
return;
}
NSLog(@"發(fā)送的數(shù)據(jù)---(%@)",dict);
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
//字典轉(zhuǎn)data結(jié)果判斷
if (error) {
return;
}
NSMutableData *printData = [[NSMutableData alloc] initWithData:jsonData];
//拼接結(jié)束符
[printData appendData:[GCDAsyncSocket CRLFData]];
// withTimeout -1 : 無窮大,一直等
[self.clientSocket writeData:printData withTimeout:-1 tag:0];
}
客戶端
#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>
@property (nonatomic, strong) GCDAsyncSocket *socketClient;
/*
lo 本地回環(huán) (Loopback)
en 無線網(wǎng) (WiFi)
pdp_ip 蜂窩網(wǎng)絡(luò) (Cellular)
awdl 通信Wi-Fi (Apple Wireless Direct Link,用于AirDrop、AirPlay、GameKit 和 Apple Pencil )
utun 虛擬隧道 (VPN)
ipsec 虛擬隧道 (VPN)
llw 低延遲無線局域網(wǎng)(Low-latency WLAN)
*/
/// 獲取ip地址
/// - Parameter isCellular: 是否獲取蜂窩網(wǎng)絡(luò)ip
- (NSString *)deviceIPAdressIsCellular:(BOOL)isCellular {
NSString *address = @"";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
success = getifaddrs(&interfaces);
if (success == 0) { // 0 表示獲取成功
temp_addr = interfaces;
while (temp_addr != NULL) {
if( temp_addr->ifa_addr->sa_family == AF_INET) {
if (isCellular) {
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"pdp_ip0"]) {
// 找到4G網(wǎng)絡(luò)接口
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
} else {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
return address;
}
- (void)createLocalClient {
NSString *ip = [self deviceIPAdressIsCellular:NO];
NSString *port = @"84999";//設(shè)置自己的端口
if (self.socketClient == nil) {
self.socketClient = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
if (self.socketClient.isConnected == NO) {
BOOL isSuccess = [self.socketClient connectToHost:ip onPort:[port integerValue] error:nil];
if (!isSuccess) {
NSLog(@"連接失敗");
}
}
} else {
BOOL isSuccess = [self.socketClient connectToHost:ip onPort:[port integerValue] error:nil];
if (!isSuccess) {
NSLog(@"連接失敗");
}
}
}
#pragma mark - GCDAsyncSocketDelegate -
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
NSLog(@"Socket連接成功");
if (_socketClient) {
self.reconnectionsNumber = 0;
self.isConnect = YES;
// -1 永不失效
[_socketClient readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
}
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"--%@-Socket斷開連接--err = %@ --- code = %ld",[NSDate date],err.localizedDescription,(long)err.code);
//這里可以做嘗試重連
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self createLocalClient];
});
}
//獲取數(shù)據(jù)失敗時(shí),會(huì)被調(diào)用
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error {
NSLog(@"connection failed: %@",[error localizedDescription]);
}
#pragma mark - 讀數(shù)據(jù)
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
//接收到的消息處理
NSData *newData = [data subdataWithRange:NSMakeRange(0, data.length-2)];
//先嘗試轉(zhuǎn)字典
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:newData options:kNilOptions error:nil];
if (result) {
//處理獲取到的字典數(shù)據(jù)
}
} else {
//如果字典轉(zhuǎn)換失敗,則嘗試轉(zhuǎn)換字符串
NSString *content = [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
NSLog(@"--接收到的消息-- content = %@",content);
//接收到的字符串處理
}
//持續(xù)接收數(shù)據(jù) 以CRLFData結(jié)尾即表示是一條數(shù)據(jù)(以此來斷開多個(gè)包一起發(fā)過來的粘包問題)
//如果不在讀取完以后寫這個(gè)方法,那就只讀取一次數(shù)據(jù),不會(huì)持續(xù)讀取
[self.socketClient readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
}
#pragma mark - 寫數(shù)據(jù)成功回調(diào)
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(@"------發(fā)送完成---------");
}
#pragma mark 發(fā)送文本類型消息
- (void)sendTextMessage:(NSString *)text {
if (text.length == 0 || text == nil) {
return;
}
if (!_socketClient) {
NSLog(@"socket未連接");
return;
}
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *printData = [[NSMutableData alloc] initWithData:data];
[printData appendData:[GCDAsyncSocket CRLFData]];
// withTimeout -1 : 無窮大,一直等
[self.socketClient writeData:printData withTimeout:-1 tag:0];
}
/// 發(fā)送數(shù)據(jù)(字典類型)
/// - Parameter dict: 發(fā)送的字典數(shù)據(jù)
- (void)sendTextMessageWithDict:(NSDictionary *)dict {
if (dict == nil || dict.count == 0) {
return;
}
if (!_socketClient) {
NSLog(@"socket未連接");
return;
}
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
if (error) {
return;
}
NSMutableData *printData = [[NSMutableData alloc] initWithData:jsonData];
[printData appendData:[GCDAsyncSocket CRLFData]];
// withTimeout -1 : 無窮大,一直等
[self.socketClient writeData:printData withTimeout:-1 tag:0];
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。