demo 地址 https://github.com/Liuchunqi3240/demo/tree/master/iOS_Socket/TCP
0x01 Server端
server端使用CocoaAsyncSocket 完成
pod 'CocoaAsyncSocket'
#import "GCDAsyncSocket.h"
@interface ViewController ()<GCDAsyncSocketDelegate>
@end
@implementation ViewController{
GCDAsyncSocket *_serverSocket;
dispatch_queue_t _golbalQueue;
NSMutableArray *_clientSocket;
}
初始化 server
- (void)initServer{
if (!_serverSocket) {
_clientSocket = [NSMutableArray array];
_golbalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_golbalQueue];
}
NSLog(@"server inited");
}
開啟服務
//啟動sever
- (void)startChatServer{
NSError *error;
//開啟一個可接受的ip(本機ip 注意:模擬器獲取不到Ip) 和 端口
[_serverSocket acceptOnInterface:@"192.168.50.128" port:2333 error:&error];
if (error) {
NSLog(@"服務器開啟失敗 error is %@",error);
}else{
NSLog(@"服務器開啟成功");
//最重要的來了,開啟后臺模式,要不然退到后臺,再回來就不管用了
[_serverSocket enableBackgroundingOnSocket];
}
}
接收客戶端鏈接
#pragma mark 有客戶端建立連接的時候調用
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
NSLog(@"new clientSocket Ip is %@",newSocket.connectedHost);
[_clientSocket addObject:newSocket];
//newSocket為客戶端的Socket。這里讀取數據
[newSocket readDataWithTimeout:-1 tag:100];
}
給客戶端回消息
[sock writeData:[@"message ..." dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
#pragma mark - GCDAsyncSocketDelegate
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
[sock readDataWithTimeout:-1 tag:100];
}
收到客戶端發來的消息
#pragma mark - GCDAsyncSocketDelegate
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
//接收到數據
NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"服務端收到的數據:%@",receiverStr);
[sock writeData:[@"mes received" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
}
0x02 客戶端 (Client)
client 端使用原生sdk編寫
@interface ViewController ()<NSStreamDelegate>
@property (weak, nonatomic) IBOutlet UITextField *mesTextField;
@end
@implementation ViewController{
NSInputStream *_inputStream;
NSOutputStream *_outputStream;
}
連接到server
- (void)connectServer{
NSString *host = @"192.168.50.128";
int port = 2333;
//創建輸入輸出流
CFReadStreamRef readStreamRef;
CFWriteStreamRef writeStreamRef;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStreamRef, &writeStreamRef);
_inputStream = (__bridge NSInputStream *)(readStreamRef);
_outputStream = (__bridge NSOutputStream *)(writeStreamRef);
_inputStream.delegate = self;
_outputStream.delegate = self;
// 輸入輸出流必須加入主運行runLoop中
[_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[_inputStream open];
[_outputStream open];
}
給服務端發送消息
- (IBAction)sendMes:(id)sender {
NSString *msg = self.mesTextField.text;
NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
[_outputStream write:msgData.bytes maxLength:msgData.length];
self.mesTextField.text = @"";
NSLog(@"客戶端發送消息:%@",msg);
}
NSStreamDelegate
#pragma MARK - NSStreamDelegate
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
switch(eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"客戶端輸入輸出流打開完成");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"客戶端有字節可讀");
//讀取服務端發來的消息
[self readData];
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"客戶端可以發送字節");
break;
case NSStreamEventErrorOccurred:
NSLog(@"客戶端連接出現錯誤");
break;
case NSStreamEventEndEncountered:
NSLog(@"客戶端連接結束");
//關閉輸入輸出流
[_inputStream close];
[_outputStream close];
//從主運行循環移除
[_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
break;
default:
break;
}
}
讀取服務端返回的消息
-(void)readData{
//建立一個緩沖區 可以放1024個字節
uint8_t buf[1024];
//返回實際裝的字節數
NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)];
//把字節數組轉化成字符串
NSData *data =[NSData dataWithBytes:buf length:len];
//從服務器接收到的數據
NSString *recStr =[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Socket:讀取從服務端發來的消息:%@",recStr);
}