Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,Socket 是纯C语言的,是 HTTP 协议的底层。
Socket 的通信过程
- 创建
Socket - 连接到服务器
- 发送数据到服务器
- 从服务器接受数据
- 关闭连接
Socket 的简单使用过程
首先,使用 Socket 需要导入以下头文件
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
创建 Socket
第一步,创建 Socket,创建的函数为
int socket(int, int, int);
三个参数分别为 domain 协议簇,指定 Socket 类型以及指定 protocol 协议。
-
常用的
domain协议族有AF_INET、AF_INET6分别代表IPV4和IPV6。 -
常用的
Socket类型有SOCK_STREAM和SOCK_DGRAM分别代表流式和数据报式。 -
协议使用 TCP协议 即填入
IPPROTO_TCP,也可以只填 0 ,它可以根据前两个参数自动获取。
函数返回一个 int 类型数据,代表 socket 的描述符,即其本身,如果失败则返回 INVALID_SOCKET 。
eg.
int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
连接到服务器
第二步,连接到服务器的函数为:
int connect(int, const struct sockaddr *, socklen_t);
第一个参数需要填入创建的 socket ,第二个参数为 sockaddr 结构指针,该结构中包含了要结合的地址和端口号,第三个参数为结构体的 size。
以下是创建 sockaddr 结构体指针的过程:
struct sockaddr_in addr;
addr.sin_family = AF_INET; // 指定协议簇
addr.sin_port = htons(12345); // 指定端口号
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 指定地址
当函数调用成功则返回 0 ,失败则返回对应的错误数值。
eg.
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(12345);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 这里要求的是一个常量地址所以进行了强转
int result = connect(clientSocket, (const struct sockaddr*)&addr, sizeof(addr));
if (result!=0) {
NSLog(@"失败");
return;
}
NSLog(@"成功");
我们可以使用终端输入 nc -lk 12345 创建对应服务器,这样就可以与客户端进行互动。
发送到服务器
第三步发送数据到服务器调用函数:
ssize_t send(int, const void *, size_t, int);
第一个参数为 socket 描述符,第二个参数为一个任意常量,第三个参数为常量的长度,第四个参数为是否阻塞,一般填 0 ,函数返回发送数据的 size 。
eg.
const char *msg = "这是一段话";
ssize_t count = send(clientSocket, msg, strlen(msg), 0);
我们可以看到运行后在终端中以及显示了对应的文字。
从服务器接收
接收与发送的方法类似:
ssize_t recv(int, void *, size_t, int);
第一个参数为 socket 描述符,第二个参数为用于接收数据的缓冲区,第三个参数为缓冲区的 size ,第四个参数一般填 0,函数返回真正接收的数据长度。
我们需要先定义一个缓冲区用于接受参数,然后调用函数获取数据。
uint8_t buffur[1024];
ssize_t recvCount = recv(clientSocket, buffur, sizeof(buffur), 0);
获取数据以后还需要将其合并并转换为 OC 字符串。
// 使用 NSData 将其转换为 data 数据
NSData *data = [NSData dataWithBytes:buffur length:recvCount];
// 再将 NSData 类型转换为 NSString
NSString *str = [[NSString alloc]initWithData:data encoding:kCFStringEncodingUTF8];
NSLog(@"%@",str);
运行后只要在终端中输入内容即可在控制台中输出。
关闭
close(clientSocket);
即可。