實現socket的監聽方法
- 使用c語言
- 使用CocoaAsyncSocket框架(內部對C的封裝)
下載
1.創建命令行工程
命令行工程.png
2.集成CocoaAsyncSocket
如果您已經熟練使用CocoaPods,請忽略此點
1.導入框架文件
TCP:UDP.png
如果編譯出現
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_GCDAsyncSocket", referenced from:
objc-class-ref in LKLScoketService.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解決辦法
添加文件.png
自定義socket服務對象
.h文件
#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"
@interface LKLSocketService : NSObject
//開啟服務
- (void)start;
@end
.m文件
#import "LKLSocketService"
@interface LKLSocketService ()<GCDAsyncSocketDelegate>
@property (strong, nonatomic) GCDAsyncSocket *socket;
@property (strong, nonatomic) NSMutableArray *clientSockets;//保存客戶端scoket
@end
@implementation LKLSocketService
- (NSMutableArray *)clientSockets
{
if (_clientSockets == nil) {
_clientSockets = [[NSMutableArray alloc]init];
}
return _clientSockets;
}
- (void)start
{
//1.創建scoket對象
GCDAsyncSocket *serviceScoket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
//2.綁定端口(5288)
//端口任意,但遵循有效端口原則范圍:0~65535,其中0~1024由系統使用或者保留端口,開發中建議使用1024以上的端口
NSError *error = nil;
[serviceScoket acceptOnPort:5288 error:&error];
//3.開啟服務(實質第二步綁定端口的同時默認開啟服務)
if (error == nil)
{
NSLog(@"開啟成功");
}
else
{
NSLog(@"開啟失敗");
}
self.socket = serviceScoket;
}
#pragma mark GCDAsyncSocketDelegate
//連接到客戶端socket
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
//sock 服務端的socket
//newSocket 客戶端連接的socket
NSLog(@"%@----%@",sock, newSocket);
//1.保存連接的客戶端socket(否則newSocket釋放掉后鏈接會自動斷開)
[self.clientSockets addObject:newSocket];
//連接成功服務端立即向客戶端提供服務
NSMutableString *serviceContent = [NSMutableString string];
[serviceContent appendString:@"話費查詢請按1\n"];
[serviceContent appendString:@"話費充值請按2\n"];
[serviceContent appendString:@"投訴建議請按3\n"];
[serviceContent appendString:@"最新優惠請按4\n"];
[serviceContent appendString:@"人工服務請按0\n"];
[newSocket writeData:[serviceContent dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
//2.監聽客戶端有沒有數據上傳
//-1代表不超時
//tag標示作用
[newSocket readDataWithTimeout:-1 tag:0];
}
//接收到客戶端數據
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//1.接受到用戶數據
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSInteger code = [str integerValue];
NSString *responseString = nil;
switch (code) {
case 1:
responseString = @"您的賬戶余額為0,請盡快充值\n";
break;
case 2:
responseString = @"系統忙,請稍后重試\n";
break;
case 3:
responseString = @"系統忙,暫時不能接受投訴建議\n";
break;
case 4:
responseString = @"請上官網查看更多優惠\n";
break;
case 0:
responseString = @"客服忙,謝謝!\n";
break;
default:
break;
}
//處理請求 返回數據
[sock writeData:[responseString dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
if (code == 0) {
[self.clientSockets removeObject:sock];
}
//CocoaAsyncSocket每次讀取完成后必須調用一次監聽數據方法
[sock readDataWithTimeout:-1 tag:0];
}
開始Socket服務
main.m文件
#import <Foundation/Foundation.h>
#import "LKLSocketService.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
//創建服務對象
LKLSocketService *socketSerview = [[LKLSocketService alloc]init];
//開始服務
[socketSerview start];
//循環運行
[[NSRunLoop mainRunLoop]run];//目的讓服務器不停止
}
return 0;
}
終端模擬客戶端
終端.png
使用Telnet命令telnet host port/telnet 192.168.10.10 5288
telnet命令是連接服務器上的某個端口對應的服務
-
通信
通信.png
Connection closed by foreign host.//斷開連接