嗨,这里是逻辑iOS技术号:一个让知识变得感性,让学习变得轻松!活跃的技术小站,希望给你的生活与技术带来意思不一样!关注公众号,回复“ 面试题 ”,即可领取更多大厂面试题型哦~ 小逻辑相信我们的生活不止眼前的苟且,还有我们向往的诗和大厂高薪工作~
Socket是什么?
要了解什么是 Socket,首先需要了解 TCP/IP、UDP!
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。
如果大家对于 七层协议模型 不是非常了解的话,你可以,沉下心来看看下面这张图:
那么TCP/IP、UDP和socket又有什么关系呢???
Socket怎么用
这里其实还有很多网络相关的知识需要科普,但是篇幅有限,如果靓仔靓女的你对于这一块有点陌生,你可以买一些网络相关的书籍
-
《TCP/IP详解 卷1:协议》
-
《图解HTTP》
-
《Unix网络编程》
-
HTTPS权威指南
Socket 传输的特点:
-
1: 传输数据为字节级,传输数据可自定义,数据量小(对于手机应用讲:费用低)
-
2: 传输数据时间短,性能高
-
3: 适合于客户端和服务器端之间信息实时交互
-
4: 可以加密,数据安全性强
正因为这些优势,常被用来做即时通讯重要媒介
上图就是通过 socket 在客户端和终端做的来回通讯
socket使用代码实现:
int socketID = socket(AF_INET, SOCK_STREAM, 0);self.clinenId= socketID;if (socketID == -1) { NSLog(@"创建socket 失败"); return;}
(滑动显示更多)
-
domain:协议域,又称协议族(family)。常用的协议族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、AF_ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
-
type:指定Socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
-
protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
-
返回值:如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET(Linux下失败返回-1)
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 结构在内存中对齐
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 编码!
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函数
-
函数参数多并且陌生
-
网络这一块知识的盲区