什么是socket,iOS中的Socket如何实现
全栈老韩
全栈工程师,擅长iOS App开发、前端(vue、react、nuxt、小程序&Taro)开发、Flutter、React Native、后端(midwayjs、golang、express、koa)开发、docker容器、seo优化等。
Socket
网络以数据包的形式进行传播
高低电平
OSI网络模型:从7层模型,合并成4层模型
- OSI的7层模型:
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
- 4层模型
- 应用层
- 传输层 (tcp, udp)
- 网络互联层 (ip)
- 网络接口层
- TCP
- 握手,建立传输数据的通道
- 可靠,数据大小不受限制,可以进行大数据传输
- 安全,可靠协议,安全送达
- 应用:数据下载
- UDP
- 不可靠,只管发送,不确认对方是否收到
- 效率高,不需要建立连接
- 数据包大小受限制,大小限制在64k之内
- 应用:直播、游戏
socket
每一个端都有socket,通过ip地址进行连接,通过端口号进行通信。
过程:创建socket,建立连接,数据读取,关闭连接
Example
引入头文件
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
模拟本地socket:
- (void)socketDemo {
// 1. 创建socket
/**
domain: 协议域, AF_INET -> ipv4
type: socket类型,SOCK_STREAM
protocol: IPPROTO_TCP
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
// 2. 连接服务器
/**
1 > 客户端socket
2 > 服务器ip地址结构体的指针
3 > 结构体数据的长度
返回值:0表示成功
*/
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int connResult = connect(clientSocket, (const struct sockaddr *)&serverAddr, sizeof(serverAddr));
if (connResult == 0) { // Success
NSLog(@"连接成功");
} else { // fail
NSLog(@"失败码 %d", connResult);
}
// 3. 发送数据
/**
1. 客户端socket
2. 发送内容的地址
3. 发送内容长度
4. 发送方式标志,一般为0
返回值:成功后发送的字节数,失效则返回SOCKET_ERROR
*/
NSString *sendMsg = @"Hello";
ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
NSLog(@"发送了 %ld 个字节", sendLen);
// 4. 从服务器接收数据
/**
1. 客户端socket
2. 接收内容的缓冲区地址
3. 接收内容缓存区长度
4. 接收方式,0表示阻塞,必须等待服务器返回数据
返回值:如果成功,则返回读入的字节数,失效则返回SOCKET_ERROR
*/
uint8_t buffer[1024]; // 准备空间
ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"接收了 %ld 个字节", recvLen);
NSData *data = [NSData dataWithBytes:buffer length:recvLen];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);
// 5. close
close(clientSocket);
}
可以在terminal终端执行命令:
nc -lk 端口号,始终监听本地计算机“端口号”的数据。Netcat是终端下用于调试和检查网络的工具包,可用于创建TCP/IP连接。
连接和发送/接收消息
@property (nonatomic, assign) int clientSocket;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// [self socketDemo];
[self doConnectionWithPort:80 addr:"61.135.169.121"];
// [self sendMsg:@"我要奋斗!!"];
NSString *request = @"GET / HTTP/1.1\n"
"Host: www.baidu.com\n\n";
[self sendMsg:request];
}
- (void)doConnectionWithPort:(int)port addr:(const char *)addr {
_clientSocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = inet_addr(addr);
int connResult = connect(_clientSocket, (const struct sockaddr *)&serverAddr, sizeof(serverAddr));
if (connResult == 0) { // Success
NSLog(@"连接成功");
} else { // fail
NSLog(@"失败码 %d", connResult);
}
}
- (void)sendMsg:(NSString *)sendMsg {
// 3. 发送数据
ssize_t sendLen = send(_clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
NSLog(@"发送了 %ld 个字节", sendLen);
// 4. 从服务器接收数据
uint8_t buffer[1024]; // 准备空间
ssize_t recvLen = recv(_clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"接收了 %ld 个字节", recvLen);
NSData *data = [NSData dataWithBytes:buffer length:recvLen];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);
}
- (void)closeSocket {
// 5. close
close(_clientSocket);
}
网络
苹果的connection有一些地方做的不是很好,比如异步下载,数据回调不来,runloop默认不开启。
线程有任务才有可能不释放。
https协议:http + ssl (RSA加密)
https不会对客户端进行验证
RSA非对称加密
公钥,私钥 == 长度大概在200位的一串数字
明文公钥加密,私密解密
私钥加密,公钥解密!
对称加密
明文密钥加密 -> 密文
密文密钥解密 -> 明文
加盐
- 一个字符串,通过拼接
- 可以使用随机盐,一个客户端一个盐,保证安全
- 也可以再加上时间戳(服务器给的),来保证安全,服务器验证当前时间或者前1分钟内的数据,那么hacker就只有在2分钟之内进行破解,增加安全性
发布于2024-02-02 10:36:21
浏览量31·
暂无评论,快来发表第一条评论吧