iOS开发轻松学习Socket

这两天很多学员都想听听关于 Socket 的内容! 所以花了一点时间就给它备了出来,公开课分享完全足够了!

这里通过文字形式纪录下来,方便大家对应学习

Socket是什么?

要了解什么是 Socket,首先需要了解 TCP/IP、UDP! 📚

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。

image

TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。

如果大家对于 七层协议模型 不是非常了解的话,你可以,沉下心来看看下面👇🏻 这张图:

image

那么TCP/IP、UDPsocket又有什么关系呢???

Socket应用层TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

image

Socket怎么用

这里其实还有很多网络相关的知识需要科普,但是篇幅有限,如果靓仔靓女的你对于这一块有点陌生,你可以买一些网络相关的书籍

  • 《TCP/IP详解 卷1:协议》
  • 《图解HTTP》
  • 《Unix网络编程》
  • HTTPS权威指南

Socket 作为一套接口,那么是怎么用的呢? 下面一图胜前言: 👇

image

Socket 传输的特点:

  • 1: 传输数据为字节级传输数据可自定义,数据量(对于手机应用讲:费用低)
  • 2: 传输数据时间短,性能高
  • 3: 适合于客户端和服务器端之间信息实时交互
  • 4: 可以加密,数据安全性强

正因为这些优势,常被用来做即时通讯重要媒介

image

上图就是通过 socket 在客户端和终端做的来回通讯

socket使用代码实现:

1: 创建socket

int socketID = socket(AF_INET, SOCK_STREAM, 0);
self.clinenId= socketID;
if (socketID == -1) {
    NSLog(@"创建socket 失败");
    return;
}
  • domain:协议域,又称协议族(family)。常用的协议族有AF_INETAF_INET6AF_LOCAL(或称AF_UNIXUnixSocket)、AF_ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
  • type:指定Socket类型。常用的socket类型有SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等。流式SocketSOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式SocketSOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
  • protocol:指定协议。常用协议有IPPROTO_TCPIPPROTO_UDPIPPROTO_STCPIPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议STCP传输协议、TIPC传输协议。

注意:1.typeprotocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。

  • 返回值:如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKETLinux下失败返回-1

2: 建立连接

int result = connect(socketID, (const struct sockaddr *)&socketAddr, sizeof(socketAddr));

if (result != 0) {
    NSLog(@"链接失败");
    return;
}
NSLog(@"链接成功");
  • 参数一:套接字描述符
  • 参数二:指向数据结构sockaddr的指针,其中包括目的端口和IP地址
  • 参数三:参数二sockaddr的长度,可以通过sizeof(struct sockaddr)获得
  • 返回值: 成功则返回0,失败返回非0,错误码GetLastError()
struct sockaddr_in socketAddr;
socketAddr.sin_family = AF_INET;
socketAddr.sin_port   = SocketPort;
struct in_addr socketIn_addr;
socketIn_addr.s_addr  = SocketIP;
socketAddr.sin_addr   = socketIn_addr;
  • __uint8_t sin_len; 假如没有这个成员,其所占的一个字节被并入到sin_family成员中
  • sa_family_t sin_family; 一般来说AF_INET(地址族)PF_INET(协议族)
  • in_port_t sin_port; // 端口
  • struct in_addr sin_addr; // ip
  • char sin_zero[8]; 没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐

3: 发送消息

if (self.sendMsgContent_tf.text.length == 0) {
    return;
}
const char *msg = self.sendMsgContent_tf.text.UTF8String;
ssize_t sendLen = send(self.clinenId, msg, strlen(msg), 0);
NSLog(@"发送 %ld 字节",sendLen);
[self showMsg:self.sendMsgContent_tf.text msgType:0];
self.sendMsgContent_tf.text = @"";
  • s:一个用于标识已连接套接口的描述字。
  • buf:包含待发送数据的缓冲区。
  • len:缓冲区中数据的长度。
  • flags:调用执行方式。
  • 返回值: 如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR.一个中文对应 3 个字节UTF8 编码!

4: 接受消息

while (1) {
    uint8_t buffer[1024];
    ssize_t recvLen = recv(self.clinenId, buffer, sizeof(buffer), 0);
    if (recvLen == 0) {
        NSLog(@"接收到了0个字节");
        continue;
    }
    // buffer -> data -> string
    NSData *data = [NSData dataWithBytes:buffer length:recvLen];
    NSString *str= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@---%@",[NSThread currentThread],str);
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showMsg:str msgType:1];
        self.sendMsgContent_tf.text = @"";
    });
}
  • 参数一: 客户端socket
  • 参数二: 接收内容缓冲区地址
  • 参数三: 接收内容缓存区长度
  • 参数四: 接收方式,0表示阻塞,必须等待服务器返回数据
  • 返回值:如果成功,则返回读入的字节数,失败则返回SOCKET_ERROR

Socket 总结

Socket 的使用还是非常简单的! 对于iOS开发有点吃力的原因是在于:

  • 都是C函数
  • 函数参数多并且陌生
  • 网络这一块知识的盲区

如果想更加傻瓜式开发,那么就请看下一个篇章: CocoaAsyncSocket 关于tcp和udp 实战
大师重磅内容(17)-CocoaAsyncSocket实现即时通讯
大师重磅内容(18)-CocoaAsyncSocket实现画板功能

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • socket学习网站:http://c.biancheng.net/view/2124.html 一.什么是soc...
    小石头呢阅读 1,198评论 0 0
  • 研究IPv6 socket编程原因: Supporting IPv6 in iOS 9 WWDC2015苹果宣布在...
    li大鹏阅读 7,169评论 7 15
  • Socket基础概念 网络中进程之间如何通信? 网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则...
    DiamondsAndRust阅读 4,681评论 2 54
  • iOS socket原理及连接过程 连接过程图解 1.网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览...
    RobinZhao阅读 2,975评论 0 5
  • 我们要讨论的是网络中进程之间如何通信? 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起! 在本地可以通过进...
    像小强一样活着阅读 2,328评论 0 14