socket编程 CocoaAsyncSocket
AsyncSocket使用 大概过程
1.建立连接
- (int)connectServer:(NSString *)hostIP port:(int)hostPort
2.连接成功后,会回调的函数
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
3.发送数据
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
4.接受数据
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
5.断开连接
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
- (void)onSocketDidDisconnect:(AsyncSocket *)sock客户端-服务端
客户端呢,首先要由一个ip地址和端口,用这个来连接服务器。
直接初始化socket(指定代理)
连接服务器
接收或者发送数据
断开连接
服务端呢
初始化监听socket开始监听客户端连接,如果有客户端连接进来,就初始化连接socket,添加到socket数组
然后开始收发数据(代理方法)
关闭连接
关键代码
#define SRV_CONNECTED 0 #define SRV_CONNECT_SUC 1 #define SRV_CONNECT_FAIL 2 #define HOST_IP @"127.0.0.1" #define HOST_PORT 8008 #import "ViewController.h" #import <AsyncSocket.h> @interface ViewController () <AsyncSocketDelegate >@property (weak , nonatomic ) IBOutlet UITextView *textView;@property (weak , nonatomic ) IBOutlet UITextField *textField;- (IBAction )connectButton:(id )sender; - (IBAction )sendButton:(UIButton *)sender; @property (nonatomic , copy ) NSString *content;@property (nonatomic , strong ) AsyncSocket *clientSocket;- (NSInteger )connecToServer:(NSString *)hostIP port:(NSInteger )hostPort; - (void )showMessage:(NSString *)message; @end @implementation ViewController #pragma mark - View lifeCycle - (void )viewDidLoad { [super viewDidLoad]; } - (void )didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (NSInteger )connecToServer:(NSString *)hostIP port:(NSInteger )hostPort { if (self .clientSocket == nil ) { self .clientSocket = [[AsyncSocket alloc] initWithDelegate:self ]; NSError *error = nil ; if (![self .clientSocket connectToHost:hostIP onPort:hostPort error:&error]) { NSLog (@"Error %ld:%@" , (long )error.code, [error localizedDescription]); UIAlertController *vc = [UIAlertController alertControllerWithTitle:[@"Connection failed to host" stringByAppendingString:hostIP] message:[NSString stringWithFormat:@"%ld:%@" ,(long )error.code,error.localizedDescription] preferredStyle:UIAlertControllerStyleAlert ]; [self presentViewController:vc animated:YES completion:^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC )), dispatch_get_main_queue(), ^{ [self dismissViewControllerAnimated:YES completion:nil ]; }); }]; return SRV_CONNECT_FAIL; }else { NSLog (@"conected server successed" ); return SRV_CONNECT_SUC; } }else { return SRV_CONNECTED; } } - (void )showMessage:(NSString *)message { UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"Alert!" message:message preferredStyle:UIAlertControllerStyleAlert ]; [self presentViewController:vc animated:YES completion:^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC )), dispatch_get_main_queue(), ^{ [self dismissViewControllerAnimated:YES completion:nil ]; }); }]; } - (IBAction )connectButton:(id )sender { NSInteger state = [self connecToServer:HOST_IP port:HOST_PORT]; switch (state) { case SRV_CONNECT_FAIL: [self showMessage:@"server error" ]; case SRV_CONNECT_SUC: [self showMessage:@"connect success" ]; break ; case SRV_CONNECTED: [self showMessage:@"connected already,don't do it again!" ]; break ; default : break ; } } - (IBAction )sendButton:(UIButton *)sender { NSString *sendStr = self .textField.text; NSString *content = [sendStr stringByAppendingString:@"\r\n" ]; NSLog (@"%@" ,content); NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding ]; [self .clientSocket writeData:data withTimeout:-1 tag:0 ]; } #pragma mark - asyncScoket delegate - (void )onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16 )port { [self .clientSocket readDataWithTimeout:-1 tag:0 ]; } - (void )onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err { NSLog (@"%@" ,err); } - (void )onSocketDidDisconnect:(AsyncSocket *)sock { NSString *msg = @"Sorry this connect is failure" ; [self showMessage:msg]; self .clientSocket = nil ; } - (void )onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long )tag { NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding ]; self .content = dataStr; NSLog (@"have received data :%@" ,dataStr); NSString *newStr = [NSString stringWithFormat:@"\n%@" ,dataStr]; self .textView.text = newStr; [self .clientSocket readDataWithTimeout:-1 tag:0 ]; } @end
#import "SocketView.h"
#import <AsyncSocket.h>
#define WELCOME_MSG 0
#define ECHO_MSG 1
#define FORMAT(format, ...) [NSString stringWithFormat:format, ##__VA_ARGS__]
@interface SocketView () <AsyncSocketDelegate >
@property (weak ) IBOutlet NSButton *stopBtn;
- (IBAction )stopButton:(id )sender;
@property (weak ) IBOutlet NSTextField *logView;
@property (weak ) IBOutlet NSTextField *portLabel;
@property (nonatomic , strong ) AsyncSocket *listenSocket;
@property (nonatomic , strong ) NSMutableArray *connectedSockets;
@property (nonatomic , assign ) BOOL isRuning;
@end
@implementation SocketView
- (void )awakeFromNib
{
self .listenSocket = [[AsyncSocket alloc] initWithDelegate:self ];
[self .listenSocket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes ]];
self .connectedSockets = [[NSMutableArray alloc] init];
self .isRuning = NO ;
[self .stopBtn setTitle:@"Start" ];
}
- (IBAction )stopButton:(id )sender {
if (!self .isRuning) {
int port = [self .portLabel intValue];
port = 8008 ;
[self .portLabel setStringValue:@"8008" ];
if (port < 0 || port > 65535 )
{
port = 0 ;
}
NSError *error = nil ;
if (![self .listenSocket acceptOnPort:port error:&error]) {
[self .logView setStringValue:FORMAT(@"Error starting server: %@" , error)];
return ;
}
[self .logView setStringValue:FORMAT(@"Echo server started on port %hu" , [self .listenSocket localPort])];
self .isRuning = YES ;
[self .portLabel setEnabled:NO ];
[self .stopBtn setTitle:@"Stop" ];
}
else
{
[self .listenSocket disconnect];
int i;
for (i = 0 ; i < [self .connectedSockets count]; i++)
{
[[self .connectedSockets objectAtIndex:i] disconnect];
}
[self .logView setStringValue:@"Stopped Echo server" ];
self .isRuning = false ;
[self .portLabel setEnabled:YES ];
[self .stopBtn setTitle:@"Start" ];
}
}
#pragma mark - asyncSocket Delegate
- (void )onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
[self .connectedSockets addObject:newSocket];
}
- (void )onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16 )port
{
[self .logView setStringValue:FORMAT(@"Accepted client %@:%hu" , host, port)];
NSString *welcomeMsg = @"恭喜您,已经通过scoket连接上服务器!" ;
NSLog (@"welcomeMsg:%@" ,welcomeMsg);
NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding ];
[sock writeData:welcomeData withTimeout:-1 tag:0 ];
}
- (void )onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long )tag
{
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0 ];
}
- (void )onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long )tag
{
NSData *readData = [data subdataWithRange:NSMakeRange (0 , data.length -2 )];
NSString *recvMessage = [[NSString alloc] initWithData:readData encoding:NSUTF8StringEncoding ];
NSString *recv = [NSString stringWithFormat:@"用户%zd:%@" ,[self .connectedSockets indexOfObject:sock],recvMessage];
if (recvMessage) {
[self .logView setStringValue:recv];
NSLog (@"%@" ,recv);
}
else
{
[self .logView setStringValue:@"Error converting received data into UTF-8 String" ];
NSLog (@"Error converting received data into UTF-8 String" );
}
NSString *backStr = nil ;
for (AsyncSocket *subSock in self .connectedSockets) {
if ([subSock isEqual:sock]) {
backStr = [NSString stringWithFormat:@"我说: %@" ,recvMessage];
}
else
{
backStr = [NSString stringWithFormat:@"ta说: %@" ,recvMessage];
}
}
NSData * backData = [backStr dataUsingEncoding:NSUTF8StringEncoding ];
[sock writeData:backData withTimeout:-1 tag:0 ];
}
- (void )onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
[self .logView setStringValue:FORMAT(@"Client Disconnected: %@:%hu" , [sock connectedHost], [sock connectedPort])];
NSLog (@"%@" ,FORMAT(@"Client Disconnected: %@:%hu" , [sock connectedHost], [sock connectedPort]));
}
- (void )onSocketDidDisconnect:(AsyncSocket *)sock
{
[self .connectedSockets removeObject:sock];
}
- (BOOL )onSocketWillConnect:(AsyncSocket *)sock
{
return YES ;
}
@end