iOS,Socker编程

1.网络的各个协议git

2.Socket原理github

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

网络七层协议并发

应用层:
1.用户接口、应用程序;socket

2.Application典型设备:网关;tcp

3.典型协议、标准和应用:TELNET、FTP、HTTPide

表示层:
1.数据表示、压缩和加密presentation工具

2.典型设备:网关

3.典型协议、标准和应用:ASCLL、PICT、TIFF、JPEG|MPEG

4.表示层至关于一个东西的表示,表示的一些协议,好比图片、声音和视频MPEG。

会话层:
1.会话的创建和结束;

2.典型设备:网关;

3.典型协议、标准和应用:RPC、SQL、NFS、X WINDOWS、ASP

传输层:
1.主要功能:端到端控制Transport;

2.典型设备:网关;

3.典型协议、标准和应用:TCP、UDP、SPX

网络层:
1.主要功能:路由、寻址Network;

2.典型设备:路由器;

3.典型协议、标准和应用:IP、IPX、APPLETALK、ICMP;

数据链路层:
1.主要功能:保证无差错的疏忽链路的data link;

2.典型设备:交换机、网桥、网卡;

3.典型协议、标准和应用:802.二、802.3ATM、HDLC、FRAME RELAY;

物理层:
1.主要功能:传输比特流Physical;

2.典型设备:集线器、中继器

3.典型协议、标准和应用:V.3五、EIA/TIA-232.

 

 

 http协议   对应于应用层 

 tcp协议    对应于传输层  

 ip协议     对应于网络层 

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

TCPTransmission Control Protocol,传输控制协议)是面向链接的协议,也就是说,在收发数据前,必须和对方创建可靠的链接。

 

UDPUser Data Protocol,用户数据报协议)

(1) UDP是一个非链接的协议,传输数据以前源端和终端不创建链接,当它想传送时就简单地去抓取来自应用程序的数据,并尽量快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每一个消息段放在队列中,应用程序每次从队列中读一个消息段。

(2) 因为传输数据不创建链接,所以也就不须要维护链接状态,包括收发状态等,所以一台服务机可同时向多个客户机传输相同的消息。

(3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。

(4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。

(5)UDP使用尽最大努力交付,即不保证可靠交付,所以主机不须要维持复杂的连接状态表(这里面有许多参数)。

(6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,所以,应用程序须要选择合适的报文大小。

 

     咱们在传输数据时,能够只使用传输层(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)

例:服务端在Windows电脑上找个第三方工具

//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
相关文章
相关标签/搜索