iOS Socket

网络:

服务器

客户端

  • 网络架构:
    CS:Client Server 客户端(Android iOSC、C++)和服务器
    BS:Browser Server 浏览器 (web前端)和 服务器(Java)
  • 长链接:客户端请求服务器建立链接,链接成功后理论上会一直保持链接 可以随时客户端和服务器进行数据传输
  • 短链接:客户端请求服务器建立链接并传输数据给服务器 服务器接收到数据后给客服端返回数据 返回之后 链接断开
  • Socket:是基于TCP协议 和 UDP协议数据传输的方法集
image.png
  • 端口:有0-25535个端口 1000以内是系统预留端口


    image.png

    image.png

    image.png
  • TCP协议:链接协议“三次握手”保证数据安全到达

  • UDP协议:非链接协议 可以广播一对多 不能保证数据安全性,传输效率高(省去了建立链接的过程)

image.png

Socket详解

image.png

AsyncSocket 框架

  • 1.Socket创建TCP服务器


    image.png
  • 2.Socket创建TCP客户端


    image.png
  • 3.发送数据


    image.png
    1. Socket服务器接收数据的协议方法


      image.png
  • 5.文件传输


    image.png
  • 6.简易的聊天工具


    image.png

ViewController.m

#import "ViewController.h"
#import "GCDAsyncSocket.h"
@interface ViewController ()<GCDAsyncSocketDelegate>
@property(nonatomic,strong)GCDAsyncSocket *serverSocket;
@property(nonatomic,strong)GCDAsyncSocket *clientSocket;
@property(nonatomic,strong)NSMutableArray *sockets;
@property (weak, nonatomic) IBOutlet UITextField *scoketTF;
@property (weak, nonatomic) IBOutlet UITextField *clientTF;
@property (weak, nonatomic) IBOutlet UITextView *textvView;
@property(nonatomic,strong)NSMutableData *fileData;
@property(nonatomic)NSInteger fileLength;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.fileData = [NSMutableData data];
    self.sockets = [NSMutableArray array];
    self.serverSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    //监听端口 等待被人链接
    [self.serverSocket acceptOnPort:8000 error:nil];
}
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
    NSLog(@"有新的socket链接进来");
    [self.sockets addObject:newSocket];
    //跟客户端要数据
    [newSocket readDataWithTimeout:-1 tag:self.sockets.count];
}
//已经读取到数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag{
    NSString *text = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    if (text.length>0) {
        //得到对方的IP地址
        NSString *host = sock.connectedHost;
        self.textvView.text = [self.textvView.text stringByAppendingFormat:@"\n%@说:%@",host,text];
        //给客户端返回数据
        [sock writeData:[@"我是服务器 我收到了!"dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }else{//接收到的是图片
        [self.fileData appendData:data];
        UIImage *image = [UIImage imageWithData:self.fileData];
        //判断如果数据接收完成才需要显示界面中
        NSLog(@"服务器接收到:%@",text);
        if(self.fileData.length == self.fileLength){
        UIImageView *iv = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
        iv.image = image;
        [self.view addSubview:iv];
      }
        
    }
    //跟客户端继续要数据
    [sock readDataWithTimeout:-1 tag:0];
}
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"已经断开链接");
    [self.sockets removeObject:sock];
}
- (IBAction)senderAction:(UIButton*)sender {
    self.clientSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    [self.clientSocket connectToHost:self.scoketTF.text onPort:8000 error:nil];
    if (sender.tag == 0) {
        [self.clientSocket writeData:[self.clientTF.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
        //显示自己说的内容
        self.textvView.text = [self.textvView.text stringByAppendingFormat:@"\n我说:%@",self.clientTF.text];
    }else{
        NSString *path = [[NSBundle mainBundle]pathForResource:@"timg2" ofType:@"jpg"];
        NSData *imageData = [NSData dataWithContentsOfFile:path];
        self.fileLength = imageData.length;
        [self.clientSocket writeData:imageData withTimeout:-1 tag:0];
    }
}

推荐阅读更多精彩内容