OSI:
开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。它从低到高分别是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
物理层:物理层并不是物理媒体本身,它只是开放系统中利用物理媒体实现物理连接的功能描述和执行连接的规程。物理层提供用于建立、保持和断开物理连接的机械的、电气的、功能的和过程的条件。简而言之,物理层提供有关同步和全双工比特流在物理媒体上的传输手段,其典型的协议有RS 232C、RS 449/422/423、V.24和X.21、X.21bis等。
端口号:每一个应用程序有很多的服务!每一个服务对应着一个端口号。
数据链路层:数据链路可以粗略地理解为数据通道。物理层要为终端设备间的数据通信提供传输介质及其连接。
网络层:选择最优路径
// 客户端socket
#import "ViewController.h"
#import "GCDAsyncSocket.h"
@interface ViewController ()
@property(nonatomic,strong)GCDAsyncSocket *clientSocket;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.clientSocket connectToHost:@"127.0.0.1" onPort:1234 error:NULL];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark GCDAsyncSocketDelegate
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
NSLog(@"已经连接成功后调用");
[self.clientSocket readDataWithTimeout:-1 tag:0];
}
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
// 发送数据
NSString *str = @"你好,服务器!";
[self.clientSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
// 接收数据
[self.clientSocket readDataWithTimeout:-1 tag:0];
}
#pragma mark 懒加载
-(GCDAsyncSocket *)clientSocket{
if (_clientSocket == nil) {
_clientSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue() socketQueue:NULL];
}
return _clientSocket;
}
@end
// 服务端
#import "ViewController.h"
#import "GCDAsyncSocket.h"
@interface ViewController ()// 用于监听的socket
@property(nonatomic,strong)GCDAsyncSocket *listenSocket;
// 保存用于数据交互的socket (需要强引用 但是如果群聊需要多个强引用 所以建立数组)
@property(nonatomic,strong)NSMutableArray *connectedSockets;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
- (IBAction)clickStartServer:(id)sender {
// 绑定ip&监听端口&接收新连接封装在一个方法中
BOOL success = [self.listenSocket acceptOnInterface:@"127.0.0.1" port:1234 error:nil];
if (success) {
NSLog(@"服务器开启成功");
}else{
NSLog(@"服务器开启失败");
}
}
#pragma mark GCDAsyncSocketDelegate
/**
* 已经接收到新的连接后调用
*
* @param sock 服务端用于监听的socket
* @param newSocket 服务端用于数据交互的socket
*/
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
NSLog(@"接收到来自%@的连接,其端口为%hu",newSocket.connectedHost,newSocket.connectedPort);
[self.connectedSockets addObject:newSocket];
// 设置欢迎信息
NSString *str = [NSString stringWithFormat:@"欢迎连接我的MAC服务器"];
[newSocket writeData:[str dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
// // 定时器 轮询
// [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(readData:) userInfo:newSocket repeats:YES];
// // 开启异步线程runloop(因为接收socket为异步不会执行 NSTimer)
// [[NSRunLoop currentRunLoop]run];
// 接收数据
[newSocket readDataWithTimeout:-1 tag:0];
}
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
NSLog(@"已经发送出去");
}
//-(void)readData:(NSTimer *)obj{
// // 接收数据
// GCDAsyncSocket *socket = obj.userInfo;
// [socket readDataWithTimeout:-1 tag:0];
//}
/**
* 已经接收到的数据
*
* @param sock 服务端用于数据交互的socket
* @param data 接收到的数据
* @param tag 标记
*/
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
// 接收的数据
[sock readDataWithTimeout:-1 tag:0];
// 转发给指定用户
for (GCDAsyncSocket *connetctedSocket in self.connectedSockets) {
if (connetctedSocket != sock) {
[connetctedSocket writeData:data withTimeout:-1 tag:0];
}
}
}
#pragma mark 懒加载
-(GCDAsyncSocket *)listenSocket{
if (_listenSocket == nil) {
_listenSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0) socketQueue:NULL];
}
return _listenSocket;
}
-(NSMutableArray *)connectedSockets{
if (_connectedSockets == nil) {
_connectedSockets = [NSMutableArray array];
}
return _connectedSockets;
}
@end