CocoaAsyncSocket是一個異步Socket的框架,支持TCP和UDP,GCDAsyncSocket類對應的是TCP,GCDAsyncUdpSocket類對應的是UDP。git
#import "ViewController.h"
#import "GCDAsyncSocket.h"
#include <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
@interface ViewController ()<GCDAsyncSocketDelegate>
{
GCDAsyncSocket *_clientSocket;
NSString *_loc_ipAdr,*_loc_port,*_des_ipAdress,*_des_port;
}
@property (weak, nonatomic) IBOutlet UITextView *recvTextView;
@property (weak, nonatomic) IBOutlet UITextField *sendTF;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_loc_ipAdr = [self getIPAddress];
_loc_port = @"10001";
_des_ipAdress = @"127.0.0.1";
_des_port = @"10000";
//建立socket
_clientSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
//鏈接服務器
NSError *error;
[_clientSocket connectToHost:_des_ipAdress onPort:_des_port.integerValue error:&error];
if (error) {
NSLog(@"socket 鏈接失敗");
}
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - GCDAsyncSocketDelegate
// 鏈接成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
NSLog(@"socket 鏈接成功");
// 讀取數據,必須添加,至關於主動添加一個讀取請求,否則不會執行讀取信息回調方法
[_clientSocket readDataWithTimeout:-1 tag:0];
}
// 已經斷開連接
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"socket 斷開鏈接");
}
//讀取到數據
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
// 注意:要想長鏈接,必須還要在 DidReceiveData 的 delegate 中再寫一次 [_udpSocket receiveOnce:&error]
// 讀取數據,讀取完信息後,從新向隊列中添加一個讀取請求,否則當收到信息後不會執行讀取回調方法。
[_clientSocket readDataWithTimeout:-1 tag:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.recvTextView.text = [NSString stringWithFormat:@"收到消息:%@",str];
}
//發送消息
- (IBAction)send:(id)sender {
[_clientSocket writeData:[self.sendTF.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];
}
#pragma mark - 獲取本地 IP 地址
- (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// 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;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
複製代碼
@interface ViewController ()<GCDAsyncSocketDelegate>
{
NSString *_loc_ipAdr,*_loc_port,*_des_ipAdress,*_des_port;
GCDAsyncSocket *_serviceSocket,*_clientSocket;
}
@property (weak) IBOutlet NSTextField *sendTF;
@property (unsafe_unretained) IBOutlet NSTextView *recvTextView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_loc_ipAdr = [self getIPAddress];
_loc_port = @"10001";
_des_ipAdress = @"127.0.0.1";
_des_port = @"10000";
//建立socket
_serviceSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
//監聽
NSError *error = nil;
[_serviceSocket acceptOnPort:_des_port.integerValue error:&error];
if (error != nil) {
NSLog(@"監聽出錯:%@", error);
} else{
NSLog(@"正在監聽...");
}
// Do any additional setup after loading the view.
}
// 接收到客戶端的鏈接請求
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
// 讀取數據,必須添加,至關於主動添加一個讀取請求,否則不會執行讀取信息回調方法
[newSocket readDataWithTimeout:-1 tag:0];
NSLog(@"收到客戶端鏈接....");
//獲取客戶端的socket
_clientSocket = newSocket;
}
// 已經斷開連接,協議方法
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
NSLog(@"socket 斷開鏈接...");
}
//讀取到數據
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
// 注意:要想長鏈接,必須還要在 DidReceiveData 的 delegate 中再寫一次 [_udpSocket receiveOnce:&error]
// 讀取數據,讀取完信息後,從新向隊列中添加一個讀取請求,否則當收到信息後不會執行讀取回調方法。
[sock readDataWithTimeout:-1 tag:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.recvTextView.string = [NSString stringWithFormat:@"收到消息:%@",str];
}
- (IBAction)send:(id)sender {
[_clientSocket writeData:[self.sendTF.stringValue dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
- (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// 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;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
@end
複製代碼