1.使用三方库AsyncSocket(对socket套接字封装),这里只演示tcp方式的通讯 2.ViewController 作为Server端. SendViewController作为Client端, 3.注意点: 1>服务器端注意点 服务器中NSMutableArray *allClientArray; 用来存放所有的socket连接,不然客户端连接之后就会断开 连接成功后死等数据过来 [newSocket readDataWithTimeout:-1 tag:200]; 2>客户端注意点 ...
#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