博客> IOS网络入门-Socket套接字
IOS网络入门-Socket套接字
2019-10-23 05:53 评论:0 阅读:1350 小白进化史
ios socket 网络

Tip1:网络基础 1.计算机网络三部分组成: (1)资源子网:面向用户的部分,负责全网络面向应用的数据处理。 (2)通信子网:负责数据通信 (3)通信协议:通信双方必须遵守的规则和约定。 2.分类:广域网、局域网 3.网络体系结构 OSI(Open System Interconnection)开放系统网络互联: (1)物理层:物理设备,原始比特流传输 (2)数据链路层:网桥,原始比特流—>逻辑传输线路(4.CRC编码) (3)网络层:控制子网的运行(3.IP协议) (4)传输层:负责数据传递,分段传输数据(2.TCP/UDP协议) (5)会话层:不参与具体的传输,验证和会话管理 (6)表示层:信息的语法语意(加密解密,转换翻译,压缩解压) (7)应用层:提供网络服务接口的应用程序(1.HTTP/FTP/SMTP/POP3) 注意:红色部分为TCP/IP协议的层次

 D3951B0F-6B2D-471F-8DD5-EE7DD8FD5632.png

4.协议:网络数据传输的规则 (1)UDP:不可靠传输(不需要接收方确认),没有建立初始化链接(没有握手),要求程序员编程验证,可以实现广播发送。(邮件的发送) (2)TCP协议:需要建立链接,需要对方确认。 问题1:UTP和TCP的相同点,不同点? (3)TCP/IP协议组合协议(传输控制协议/互联网协议)(http协议的基协议): INTERNET的基础协议,规范了网络上的所有通信设备。 Tip2:Socket套接字 1.定义:通信的基石,支持TCP/IP协议的网络通信的基础操作单元。本身不是协议,是一个基于TCP/IP协议封装出来的接口,通过它才能实现TCP/IP协议。 2、在TCP/IP通信层中,应用层通过传输层进行数据通信时,TCP会同时遇到多个应用程序进程提供并发服务的问题。多个TCP连接或者多个应用程序进程可能许啊哟通过同一个TCP协议端口传输数据。为了区别不同的应用程序接口和连接,操作系统为应用程序与TCP/IP协议交互提供了套接子(Sccket接口)。应用层可以和可以和传输层通过Socket接口,区分来自不同应用程序进程或者=网络连接的通信,实现数据传输的并发服务。 补充:端口 计算机“端口”是英文port的义译,可以认为是计算机与外界通讯交流的出口。其中硬件领域的端口又称接口,如:USB端口、串行端口等。软件领域的端口一般指网络中面向连接服务和无连接服务的通信协议端口,是一种抽象的软件结构,包括一些数据结构和I/O(基本输入输出)缓冲区。

按端口号可分为3大类:

(1)公认端口(Well Known Ports):从0到1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯。

(2)注册端口(Registered Ports):从1024到49151。它们松散地绑定于一些服务。也就是说有许多服务绑定于这些端口,这些端口同样用于许多其它目的。例如:许多系统处理动态端口从1024左右开始。

(3)动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535。理论上,不应为服务分配这些端口。实际上,机器通常从1024起分配动态端口。但也有例外:SUN的RPC端口从32768开始。 3、Socket通信示意图

 8560D7A5-578B-421D-B7BD-CF1C90E80C9F.png

注意:上图服务器端少了一个绑定IP的过程。 服务器端 客户端 (1)初始化一个Socket <—————— (1)初始化一个Socket (2)绑定IP:bind( ) //客户端不用绑定IP,默认使用本机的IP拨号 (3)监听:listen()—>accept( ) <—————— (2)建立链接:connect( 服务器端的IP )
(4)处理:receive( ) / send( ) <—————— > (3)recv( )/send( )
(4)close( ) (5)关闭:close 4、使用Socket通信的三中方式 (1)NSURL(Cocoa层) (2)CFNetwork和CFNetServices(基于C的) (3)BSD socket(基于C的)(OS层) 5、示例代码

//一.导入头文件

import

@interface ViewController (){

int _serviceSocketId;

int _clientSocketId;

}

@end

@implementation ViewController

  • (void)viewDidLoad { [super viewDidLoad]; }

/ 二 服务器端 1.创建Socket socket() 2.绑定IP地址bind() 3.监听---同意接收listen(),accept() 4.建立连接后通信:recv(),send() 5.关闭: close()/

  • (IBAction)scoket:(id)sender { /**

    • @param <#int#> IP地址类型:AF_INET == ipv4,AF_INET6 == ipv6
    • @param <#int#> Socket类型:SOCK_STREAM基于TCP/IP协议
    • @param <#int#> Socket遵循的协议,可以设置为0,将默认遵循前一个参数基于的协议
    • @return socketId */ //1.创建scoket _serviceSocketId = socket(AF_INET, SOCK_STREAM, 0);

    NSLog(@"%d",_serviceSocketId);

}

  • (IBAction)bind:(id)sender { //绑定前判断socketId是否可用

    if (!_serviceSocketId) {

    return;

    } //2.绑定IP

    /** struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; ip地址类型 in_port_t sin_port; 端口号0-1024不要用,加字节符的转换 struct in_addr sin_addr; ip地址 char sin_zero[8]; };

    */ //sockaddr_in为sockaddr的兄弟变量,比后者更好用

    struct sockaddr_in addr;

    //初始化结构体addr /*

    • @param addr 指定初始化的结构体
    • @param <#int#> 初始化的值
    • @param <#size_t#> 初始化变量的大小
    • @return 无返回值 */ memset(&addr, 0, sizeof(addr));

      addr.sin_family = AF_INET; //htons(短整型),htonl(长整型)函数:将主机数转换为网络字节数 addr.sin_port = htons(5678); //设置IP地址 addr.sin_addr.s_addr = htonl(INADDR_ANY); //(struct sockaddr *)&addr

      /**

    • @param _serviceSocketId 绑定的socketId
    • @param sockaddr
    • @param <#socklen_t#> socketId的长度
    • @return 返回值 成功 1,失败 -1 */

    //返回值 成功 1,失败 -1 int bindId = bind(_serviceSocketId,(struct sockaddr *)&addr, sizeof(addr));

    if (bindId == -1) {

    NSLog(@"bind error");

    }

}

  • (IBAction)listen:(id)sender {

    //3.监听 /*

    • @param <#int#> 监听的socketId
    • @param <#int#> 呼入的最大链接数 */ int listenId = listen(_serviceSocketId, 10);

    if (listenId == -1) {

    NSLog(@"listen error");

    } //开辟一个子线程去执行accept()(accept会阻塞当前线程) [self performSelectorInBackground:@selector(accept) withObject:nil];

} -(void)accept{ //null 自动获取客户端的协议地址 //返回值为一个新的SocketId,专门做数据处理操作 int acceptId = accept(_serviceSocketId, NULL, NULL);

if (acceptId) {

    /**
     *  @param <#int#>        新的socketId
     *  @param #>         接收数据的容器
     *  @param <#size_t#>     容器的大小
     *  @param <#int#>         目前用不到
     *
     *  @return          long
     */
    //创建字符数组接收数据
    char str[1000];
   long recvid = recv(acceptId, &str, 1000, 0);

    if (recvid == -1) {

        NSLog(@"recvid error");
    }
    NSLog(@"str is :%s",str);

    close(acceptId);

}

}

  • (IBAction)close:(id)sender {

    close(_serviceSocketId); }

    /-----------------客户端-----------------/

/**

  • 三 客户端 1.创建Socket socket() 2.链接服务器 connect() 3.建立连接后通信 4.关闭 */
  • (IBAction)cScoket:(id)sender {

    //1.创建scoket _clientSocketId = socket(AF_INET, SOCK_STREAM, 0);

    NSLog(@"%d",_clientSocketId);

}

  • (IBAction)cConnect:(id)sender {

    //2.连接服务器 struct sockaddr_in addr;

    //初始化 memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;

    addr.sin_port = htons(5678); / 设置地址: 1.地址类型 2.地址字符串 3.将要设置的地址变量 / //连接到服务器端的地址 inet_pton(AF_INET,"192.168.10.133", &addr.sin_addr);

    int connectId = connect(_clientSocketId, ( struct sockaddr*)&addr, sizeof(addr));

    if (connectId == -1) {

    NSLog(@"connect error");

    } /**

    • @param <#int#> SocketId
    • @param #> <##> 发送内容
    • @param <#size_t#> 发送内容长度
    • @param <#int#> 暂时不用
    • @return long / char str = "hehe"; long sendId = send(_clientSocketId, str, strlen(str), 0);

    if (sendId == -1) {

    NSLog(@"send error");

    }

} //如果不关闭,会出现端口占用的情况

  • (IBAction)cClose:(id)sender {

    close(_clientSocketId); }

收藏
0
sina weixin mail 回到顶部