iOS学习——Socket

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);

 

以上是关于iOS学习——Socket的主要内容,如果未能解决你的问题,请参考以下文章

Java IO学习笔记四:Socket基础

通过 c# 与 socket.io 服务器通信

学习 Socket.io

一次与两个用户随机聊天(Socket.io)

如何开始socket.io学习?

iOS学习——Socket