IOS TCP通信

#import <UIKit/UIKit.h>

// 包含了tcp的socket(GCD/Blocks版本)
#import "GCDAsyncSocket.h"

// 這是一個接收 消息界面
@interface ViewController : UIViewController <GCDAsyncSocketDelegate> {
    // 申明一個變量名 TCP socket鏈接
    GCDAsyncSocket *serverSocket;
    
    // 用來存放全部的socket鏈接
    NSMutableArray *allClientArray;
}


@end
#import "ViewController.h"
#import "SendViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.navigationItem.title = @"接收消息";
    [self showNavItem];
    
    [self createTcpSocket];
}

- (void) createTcpSocket {
    allClientArray = [NSMutableArray array];
    
    // 建立一個後臺的隊列 等待接收數據
    dispatch_queue_t dQueue = dispatch_queue_create("My socket queue", NULL);
    // 1. 建立一個tcp socket套接字對象
    serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dQueue socketQueue:nil];
    // 2. 綁定監聽端口
    [serverSocket acceptOnPort:12345 error:nil];
}

#pragma mark - 代理方法 接收到一個請求
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
    NSString *ip = [newSocket connectedHost];
    uint16_t port = [newSocket connectedPort];
    // 這個代理函數被調用的時候就是表示 有人鏈接我了
    // newSocket就是新的socket
    NSLog(@"new socket [%@:%d] is %@", ip, port, newSocket);
    
    [allClientArray addObject:newSocket];
    // 一直死等讀取newSocket的消息
    [newSocket readDataWithTimeout:-1 tag:200];
    // 寫一些echo信息
    NSString *s = @"Welcome";
    NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding];
    [newSocket writeData:data withTimeout:60 tag:300];
}
#pragma mark - 接收到數據代理函數
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *ip = [sock connectedHost];
    uint16_t port = [sock connectedPort];

    NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"接收到tcp [%@:%d] %@", ip, port, s);
    
    NSString *s2 = [NSString stringWithFormat:@"你發的數據是:%@", s];
    NSData *databack = [s2 dataUsingEncoding:NSUTF8StringEncoding];
    [sock writeData:databack withTimeout:60 tag:400];
    
    // 再次接收數據 由於這個方法只接收一次
    [sock readDataWithTimeout:-1 tag:200];
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
    NSLog(@"失去鏈接 %@", err);
    [allClientArray removeObject:sock];
}

- (void) showNavItem {
    UIBarButtonItem *sendMyself = [[UIBarButtonItem alloc] initWithTitle:@"發送本身" style:UIBarButtonItemStylePlain target:self action:@selector(sendMyself)];
    self.navigationItem.rightBarButtonItem = sendMyself;
}
- (void) sendMyself {
    SendViewController *svc = [[SendViewController alloc] init];
    [self.navigationController pushViewController:svc animated:YES];
}
#import <UIKit/UIKit.h>
#import "GCDAsyncSocket.h"

@interface SendViewController : UIViewController <GCDAsyncSocketDelegate> {
    // 這個socket用來作發送使用 固然也能夠接收
    GCDAsyncSocket *sendTcpSocket;
}

@end
#import "SendViewController.h"
#import "MBProgressHUD.h"

@interface SendViewController ()

@end

@implementation SendViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    self.navigationItem.title = @"發送";

    [self showNavItem];
    [self createClientTcpSocket];
}

- (void) showNavItem {
    UIBarButtonItem *sendMsg = [[UIBarButtonItem alloc] initWithTitle:@"發送消息" style:UIBarButtonItemStylePlain target:self action:@selector(sendMsg)];
    self.navigationItem.rightBarButtonItem = sendMsg;
}

- (void) createClientTcpSocket {
    dispatch_queue_t dQueue = dispatch_queue_create("client tdp socket", NULL);
    // 1. 建立一個 udp socket用來和服務端進行通信
    sendTcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dQueue socketQueue:nil];
    // 2. 鏈接服務器端. 只有鏈接成功後才能相互通信 若是60s鏈接不上就出錯
    NSString *host = @"10.0.161.119";
    uint16_t port = 12345;
    [sendTcpSocket connectToHost:host onPort:port withTimeout:60 error:nil];
    // 鏈接必須服務器在線
}
#pragma mark - 代理方法表示鏈接成功/失敗 回調函數
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"鏈接成功");
    // 等待數據來啊
    [sock readDataWithTimeout:-1 tag:200];
}
// 若是對象關閉了 這裏也會調用
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
    NSLog(@"鏈接失敗 %@", err);
    // 斷線重連
    NSString *host = @"10.0.161.119";
    uint16_t port = 12345;
    [sendTcpSocket connectToHost:host onPort:port withTimeout:60 error:nil];
}
#pragma mark - 消息發送成功 代理函數
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    [MBProgressHUD hideHUDForView:self.view animated:YES];
    NSLog(@"消息發送成功");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *ip = [sock connectedHost];
    uint16_t port = [sock connectedPort];
    NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"接收到服務器返回的數據 tcp [%@:%d] %@", ip, port, s);
}
- (void) sendMsg {
    // 寫這裏代碼
    NSString *s = @"hello from yang";
    NSData *data = [s dataUsingEncoding:NSUTF8StringEncoding];
    // 開始發送
    [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    // 發送消息 這裏不須要知道對象的ip地址和端口
    [sendTcpSocket writeData:data withTimeout:60 tag:100];
}
- (void)dealloc {
    NSLog(@"dealloc");
    // 關閉套接字
    [sendTcpSocket disconnect];
    sendTcpSocket = nil;
}

@end
相關文章
相關標籤/搜索