Socket编程
socket编程
CocoaAsyncSocket
- 开源库:https://github.com/robbiehanson/CocoaAsyncSocket
- CocoaAsyncSocket介绍
- TCP
GCDAsyncSocket
AsyncSocket
- UDP
GCDAsyncUdpSocket
AsyncUdpSocket
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数组
- 然后开始收发数据(代理方法)
- 关闭连接
关键代码
- 客户端
|
- 服务端
@interface SocketView () <AsyncSocketDelegate>
@property (weak) IBOutlet NSButton *stopBtn;
- (IBAction)stopButton:(id)sender;
@property (weak) IBOutlet NSTextField *logView;
@property (weak) IBOutlet NSTextField *portLabel;
/**监听socket*/
@property (nonatomic, strong) AsyncSocket *listenSocket;
/**socket连接数组*/
@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
{
// 停止监听socket
[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"];
}
}
/**
* 接受客户端连接
*
* @param sock 监听socket
* @param newSocket 新连接
*/
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
{
[self.connectedSockets addObject:newSocket];
}
/**
* 已经与客户端建立连接
*
* @param sock 连接1
* @param host 客户端ip
* @param port 连接端口
*/
- (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];
}
/**
* 发送数据到客户端
*
* @param sock 连接
* @param tag 标识
*/
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];
}
/**
* 接收客户端数据
*
* @param sock 连接1
* @param data 数据
* @param tag 标识
*/
- (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];
}
/**
* 将要断开连接
*
* @param sock 连接1
* @param err 错误码
*/
- (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]));
}
/**
* 已经断开连接·
*
* @param sock 连接1
*/
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{
[self.connectedSockets removeObject:sock];
}
- (BOOL)onSocketWillConnect:(AsyncSocket *)sock
{
return YES;
}
@end