iOS Socket编程入门指北

本文介绍了iOS Socket编程的基础,包括Socket四元组、连接过程、字节序转换,以及如何处理粘包和断包问题。此外,还详细讲解了Protocol Buffers(Protobuf)的概念、语法、编译器使用,并阐述了其在数据传输中的高效性和节省流量的特性。最后,给出了使用Socket保持长连接和心跳包的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iOS Socket编程入门指北

1.Socket及Socket四元组

1.1 Socket是什么?

Socket 的原意是“插座”,在计算机通信领域,Socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 Socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

1.2 Socket通信

在这里插入图片描述
Socket一般分为TCP网络编程和UDP网络编程。我们下面讲的内容是基于TCP的网络编程。

1.3 Socket四元组

在这里插入图片描述

2.Socket连接过程

在这里插入图片描述

3.大端序、小端序及主机字节序、网络字节序

3.1 大端序(Big Endian)

大端序(Big Endian):高位字节存放到低位地址(高位字节在前)

eg,我有两个分别需要4个字节存储的整数,为了方便说明,使用16进制表示这两个数,即0x12345678和0x11223344。
在这里插入图片描述

3.2 小端序(Little Endian)

小端序(Little Endian):高位字节存放到高位地址(低位字节在前)

在这里插入图片描述

3.3 主机字节序

主机字节序: 指的是计算机本身是大端序还是小端序。

3.4 网络字节序

两台主机之间进行通信,有的主机是大端序,有的主机是小端序,如果保证能正常通信呢?

TCP/IP协议隆重出场,RFC1700规定使用“大端”字节序为网络字节序。

3.5 常用的网络字节序和主机字节序转换函数

常见的网络字节转换函数有:

 - htons():host to network short,将short类型数据从主机字节序转换为网络字节序。
 - ntohs():network to host short,将short类型数据从网络字节序转换为主机字节序。 
 - htonl():host to network long,将long类型数据从主机字节序转换为网络字节序。 
 - ntohl():network to host long,将long类型数据从网络字节序转换为主机字节序。

3.6 测试当前主机环境是大端序还是小端序

#include <stdio.h>
int main ()
{
  unsigned int x = 0x12345678;
  char *c = (char*)&x;
  if (*c == 0x78) {
    printf("Little endian");
  } else {
    printf("Big endian");
  }
  return 0;
}

4.自定义协议

Socket收发的消息我们如何区分消息类型呢?如何知道每一个包的大小呢?
在这里插入图片描述

5.Socket组包、拆包、处理粘包、断包

5.1 概念解释

组包—按照约定的协议格式进行组装数据。

粘包—简单地说就是客户端收到的数据大于1条。

粘包产生的原因:
TCP的优化算法Nagle算法。它将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。就是为了减少广域网的小分组数目,从而减小网络拥塞的出现。
发送端需要等缓冲区满才发送出去,造成粘包。
接收方不及时接收缓冲区的包,造成多个包接收。

断包—应该还是比较好理解的,比如我们发送一条很大的数据包,类似图片和录音等等,很显然一次发送或者读取数据的缓冲区大小是有限的,所以我们会分段去发送或者读取数据。

5.2 处理粘包和断包

在这里插入图片描述

5.3 Socket如何保持长链接

一般的Socket正常收发完消息之后,就会断开连接(主动或被动),但是有些实时化场景要求高的地方,需要及时收发消息,比如直播间、股票期货行情模块等,要实时收发数据,这样的话就需要Socket保持连接一直在。那么如何保持Socket连接一直在呢,就是发送心跳包来保活。

6.Protobuf相关介绍

Protocol Buffer(Protobuf的全称)是一种支持多平台、多语言、可扩展的的数据序列化机制,相较于XML来说,Protobuf更小更快更简单,支持自定义的数据结构,用Protobuf编译器生成特定语言的源代码,如C++、Java、Python,目前Protobuf对主流的编程语言都提供了支持,非常方便的进行序列化和反序列化。

What are protocol buffers?
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

Protobuf官网链接

6.1 Protobuf语法

目前最新的版本是proto3, 如果.proto文件不指定proto版本的话,默认是2.0版本

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

分配字段号

As you can see, each field in the message definition has a unique number. These field numbers are used to identify your fields in the message binary format, and should not be changed once your message type is in use. Note that field numbers in the range 1 through 15 take one byte to encode, including the field number and the field's type (you can find out more about this in Protocol Buffer Encoding). Field numbers in the range 16 through 2047 take two bytes. So you should reserve the numbers 1 through 15 for very frequently occurring message elements. Remember to leave some room for frequently occurring elements that might be added in the future.

The smallest field number you can specify is 1, and the largest is 229 - 1, or 536,870,911. You also cannot use the numbers 19000 through 19999 (FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber), as they are reserved for the Protocol Buffers implementation—the protocol buffer compiler will complain if you use one of these reserved numbers in your .proto. Similarly, you cannot use any previously reserved field numbers.

如何给.proto文件添加注释
To add comments to your .proto files, use C/C+±style // and /* … */ syntax.

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */

message SearchRequest {
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.
}

如何定义一个数组类

message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}

指定字段类型
message当中的field类型包含以下两种(proto3)

  • singular: a well-formed message can have zero or one of this field (but not more than one). And this is the default field rule for proto3 syntax.
  • repeated: this field can be repeated any number of times (including zero) in a well-formed message. The order of the repeated values will be preserved.
6.2 ProtoC编译器

.proto文件转换成对应平台的类文件,需要安装protocol compiler

MAC使用ProtocolBuffer

cd 到根目录即可
我们使用 protoc 工具生成Objective-C代码:
终端输入: $ protoc --proto_path=A --objc_out=B person.proto

其中--proto_path=后跟A是需要处理的proto文件所在的文件夹,--objc_out=指明生成的是
Objective-C代码以及目标文件存放路径,B是目标文件存放路径,person.proto是需要处理的文件。

6.3 Proto为什么节省流量

Protobuf优点就是传输效率快(据说在数据量大的时候,传输效率比XML和JSON快10-20倍),序列化后体积相比JSON和XML很小,支持跨平台多语言,消息格式升级和兼容性还不错,序列化反序列化速度很快。

Protocol Buffer 序列化原理大揭秘 - 为什么Protocol Buffer性能这么好?

7.Talk is cheap, show me the code!

如需Demo源码请联系1219548455@qq.com !

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值