首页 > 移动平台 > 详细

iOS,Socker编程

时间:2017-02-12 14:29:44      阅读:261      评论:0      收藏:0      [点我收藏+]

1.网络的各个协议

2.Socket原理

3.CocoaAsyncSocket库使用

网络的各个协议

网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

OSI七层网络模型
TCP/IP四层概念模型
对应网络协议
应用层(Application)
应用层
TFTP, FTP, NFS, WAIS
表示层(Presentation)
Telnet, Rlogin, SNMP, Gopher
会话层(Session)
SMTP, DNS
传输层(Transport)
传输层
TCP, UDP
网络层(Network)
网际层
IP, ICMP, ARP, RARP, AKP, UUCP
数据链路层(Data Link)
网络接口
FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
物理层(Physical)
IEEE 802.1A, IEEE 802.2到IEEE 802.11

 http协议   对应于应用层 

 tcp协议    对应于传输层  

 ip协议     对应于网络层 

 三者本质上没有可比性。  何况HTTP协议是基于TCP连接的。 

 TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。

     我们在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层 协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。WEB使用HTTP作传输层协议,以封装HTTP文本信息,然 后使用TCP/IP做传输层协议将它发送到网络上。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

Socket原理

     3.1.套接字(Socket)概念

          套接字(Socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

          应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应 用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

   3.2.建立Socket连接

           建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。

           套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户 端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

     3.3.Socket连接与TCP连接

          创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCPUDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

     3.4.Socket连接Http连接

           由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用 中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

           而Http连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

CocoaAsyncSocket库使用

        下载地址:https://github.com/robbiehanson/CocoaAsyncSocket

 

        里面有GCDAsyncSocket(TCP)和GCDAsyncUdpSocket(UDP)

例:

//ViewController.m文件

//
//  ViewController.m
//  SockerLearn
//
//  Created by Vie on 2017/2/9.
//  Copyright ? 2017年 Vie. All rights reserved.
//

#import "ViewController.h"
#import "GCDAsyncSocket.h"
@interface ViewController ()<GCDAsyncSocketDelegate>
@property(nonatomic,strong) GCDAsyncSocket *socket;
@end

@implementation ViewController

-(GCDAsyncSocket *)socket{
    if (!_socket) {
        //创建一个socket对象,代理方法都会在子线程调用,在刷新UI时就要回到主线程
        _socket=[[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
        _socket.IPv4PreferredOverIPv6 = NO; // 设置支持IPV6

    }
    return _socket;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    float heightBtn=50;
    float widthBtn=self.view.frame.size.width*0.8;
    float btnX=(self.view.frame.size.width-widthBtn)/2;
    
    //连接服务器按钮
    UIButton *connectBtn=[[UIButton alloc] initWithFrame:CGRectMake(btnX, 100, widthBtn, heightBtn)];
    [connectBtn setTitle:@"连接服务器" forState:UIControlStateNormal];
    [connectBtn setBackgroundColor:[UIColor colorWithRed:104/255.0 green:200/255.0 blue:250/255.0 alpha:1]];
    [connectBtn.layer setCornerRadius:8.0f];
    [connectBtn addTarget:self action:@selector(connectAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:connectBtn];
    
    //登陆按钮(登陆其实就是发送消息校验)
    UIButton *loginBtn=[[UIButton alloc] initWithFrame:CGRectMake(btnX, 180, widthBtn, heightBtn)];
    [loginBtn setTitle:@"登陆验证" forState:UIControlStateNormal];
    [loginBtn setBackgroundColor:[UIColor colorWithRed:104/255.0 green:200/255.0 blue:250/255.0 alpha:1]];
    [loginBtn.layer setCornerRadius:8.0f];
    [loginBtn addTarget:self action:@selector(loginAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:loginBtn];
    
    //断开连接
    UIButton *closeBtn=[[UIButton alloc] initWithFrame:CGRectMake(btnX, 260, widthBtn, heightBtn)];
    [closeBtn setTitle:@"断开连接" forState:UIControlStateNormal];
    [closeBtn setBackgroundColor:[UIColor colorWithRed:104/255.0 green:200/255.0 blue:250/255.0 alpha:1]];
    [closeBtn.layer setCornerRadius:8.0f];
    [closeBtn addTarget:self action:@selector(closeAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:closeBtn];
    
}
//连接Socket服务
-(void)connectAction:(UIButton *)sender{
    NSLog(@"连接Socket服务器");
    NSString *host=@"192.168.191.1";
    int port=5678;
    //连接服务器
    NSError *error=nil;
    
//    [self.socket connectToHost:host onPort:port error:&error];
    //设置连接超时时间
    [self.socket connectToHost:host onPort:port withTimeout:15 error:&error];
    
    if (error) {
        NSLog(@"%@",error);
    }
}

//发送消息Socket登陆验证
-(void)loginAction:(UIButton *)sender{
    NSLog(@"发送消息Socket登陆验证");
    //登陆指令(本质是发送消息接收消息)
    NSString *loginInfo=@"Vie:123456\n";
    NSData *data=[loginInfo dataUsingEncoding:NSUTF8StringEncoding];
    //-1不设置超时
    [self.socket writeData:data withTimeout:-1 tag:0];
}

//断开Socket连接
-(void)closeAction:(UIButton *)sender{
    NSLog(@"断开Socket连接");
    [self.socket disconnect];
}

#pragma  mark  GCDAsyncSocketDelegate数据发送成功执行回调
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"数据成功发送到服务器");
    //自己调用下读取数据的方法,接着Socket才会执行didReadData(每当你接收到数据之后,需要再次设置)
    [self.socket readDataWithTimeout:-1 tag:tag];
}

#pragma mark GCDAsyncSocketDelegate接收到数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //将接收到的数据转换成字符串,中文编码要一致
    NSString *responseString=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"收到数据tag:%ld  内容:%@",tag,responseString);
   //每次读完数据后,都要调用一次监听数据的方法Socket才会执行didReadData
    [self.socket readDataWithTimeout:-1 tag:tag];
}

#pragma mark GCDAsyncSocketDelegate连接服务器结果回调
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"连接主机成功");
}

-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    if (err) {
        NSLog(@"连接失败");
    }else{
        NSLog(@"正常断开");
    }
}

@end

 

iOS,Socker编程

原文:http://www.cnblogs.com/douniwanxia/p/6390842.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!