zoukankan      html  css  js  c++  java
  • iOS学习——Socket

      了解socket,就需要了解数据在网络中传输。

      网络通讯有三要素:ip地址,网络中设备的表示,例如本机用127.0.0.1,或者用本机名:localhost;端口号,用来标示进程的逻辑地址,也就是服务,有效端口0~65535,一般1024以下端口被系统或者本地服务所占据,开发中尽量不要使用,以避免冲突;通讯协议——UDP,TCP,UDP是用户数据报文协议,只负责发送数据,并不管是否被接收,不会建立联接,其会将数据和目的封装到数据包中。每个包大小为64K以内,数据传输速度很快,但是并不安全,一般用在游戏,直播之类的行业中;TCP则需要建立联接来传输数据,不会对数据做大小限制,需要通过三次握手协议来完成连接,安全可靠,缺点便是效率低。

      三次握手建立连接:

      

    首先client发送连接请求到服务器,服务器同意连接发送ACK报文,并为这次连接分配资源;client接收到ACK报文后,也向服务器发送ack报文,并为连接分配资源,这样TCP连接就建立成功。断开时采用四次挥手协议:

      client发送断开连接请求,FIN报文,服务器接收到FIN报文了,知道client已经准备好结束连接,不再传输数据,但是如果服务器端没有准备好,不用着急关闭scoket,仍然可以发送数据前往client,此时需要发送ACK报文,告诉client请等待结束,让client进去FIN_WAIT状态。当服务器确定完成数据发送并可以关闭,发送FIN报文进入client,client接收到FIN报文后,并不会立刻断开连接,为了避免错误关闭状态,例如服务器没打算关闭连接,会向服务器发送ACK报文,并会进入TIME_WAIT状态,等待2MSL后未接收到服务器回应变正式断开连接,而服务器在接收到ACK报文后也会断开连接。

      UDP会涉及到数据打包发送,这其中会需要了解osi七层模型:

      

      进行数据传输,首先应用层形成源,然后在传输层通过TCP/UDP协议包装,在网络层,确定ip和端口号(形成socket),建立数据传输io,在数据链路层打包数据,每一包数据即为一帧,最后通过物理层转为电信号,电信号的传输标示采用高低电平,其实就是01数据,即二进制数据传输,所以网络中数据传输形式都是二进制。

      了解这么多后,再来看socket概念。网络通信就是socket间的通信,需要两端都是socket,然后这两端建立IO传输。可以这样理解,socket是一种网络机制类,实例化的具体信息就是ip+端口。当我们使用qq聊天,a手机IP+qq端口发送信息,需要找到b手机IP+qq端口才能接收数据;

      socket本身是用c语言书写,方便跨平台使用,使用起来也非常简单,基本可以归位五步。一步,创建socket,第二步,建立connect,第三步,write数据,第四步read数据,第五步colse;

      

      首先,打开终端,输入命令:nc -lk 1025(监听端口号1025)

      导入头文件:

      

    #import <sys/socket.h>
    #import <netinet/in.h>
    #import <arpa/inet.h>

      按操作创建socket连接:

    1.创建socket

      

     /**
         参数
         socket三个参数传入相应值
         domain:    协议域,AF_INET -> IPV4 AF_INET6 -> IPV6
         type:      Socket 类型,SOCK_STREAM数据流/SOCK_DGRAM数据报文
         protocol: IPPROTO_TCP,如果传入0 那么会自动根据第二个参数选择合适的协议
         
         返回值
         socket
         */
    
        int clientSocket = socket(AF_INET, SOCK_STREAM, 0);

    2.连接服务器

        /**
         参数
         1> 客户端socket
         2> 指向数据结构sockaddr的指针,其中包括目的端口和IP地址
         3> 结构体数据长度
         返回值
         0 成功/其他 错误代号
         */
        struct sockaddr_in severAddr;
        severAddr.sin_family = AF_INET;
        //端口
        severAddr.sin_port = htons(1025);
        //地址
        severAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        
        int connResult =  connect(clientSocket, (const struct sockaddr *)&severAddr, sizeof(severAddr));
        if (connResult == 0) {
            NSLog(@"连接成功!!");
        }else{
            NSLog(@"失败了 %d",connResult);
            return;
        }

    3.write数据,写入hello world 可以在简单端口看到相应展示

      

     /**
         参数
         1> 客户端socket
         2> 发送内容地址
         3> 发送内容长度
         4> 发送方式标志,一般为0
         返回值
         如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
         */
        NSString * sendMsg =@"hello world";
        ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);

    4.read数据,在端口下写入me too可以看到xcode打印结果展示

      

       /**
         参数
         1> 客户端socket
         2> 接收内容缓冲区地址
         3> 接收内容缓存区长度
         4> 接收方式,0表示阻塞,必须等待服务器返回数据
         返回值
         如果成功,则返回读入的字节数,失败则返回SOCKET_ERROR
         */
        uint8_t buffer[1024];//要把空间准备出来!
        
        ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);

    5.最后便是便是关闭socket

    close(clientSocket);
  • 相关阅读:
    操作系统进程调度策略
    runnable & callable
    leetcode 124 二叉树中的最大路径和
    leetcode 24 两两交换链表中的节点
    leetcode 93 复原IP地址
    C++ 11 move
    leetcode 64 最小路径和
    leetcode 1143 最长公共子序列
    leetcode 528 按权重随机选择
    数据挖掘面试题(1)
  • 原文地址:https://www.cnblogs.com/zhulilove/p/8016557.html
Copyright © 2011-2022 走看看