一、定义
socket,用于双方通信连接以便进行数据交换,连接的双方即为socket。
二、客户端
客户端的开发需要用到以下几个方法:
创建socket,socket()
连接socket,connect()
接受消息,recv()
发送消息,send()
1、头文件及宏
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#define SocketPort htons(8081) //端口
#define SocketIP inet_addr("172.19.203.106") // ip地址
#define SocketFamily AF_INET //协议族
2、socket()
_socketID = socket(SocketFamily, SOCK_STREAM, 0);
if (_socketID == -1) {
NSLog(@"创建socket失败");
return;
}
else{
NSLog(@"创建socket成功");
}
socket() 返回一个 socketID 是 socket 的标识,在传到服务端后用于匹配客户端。
包含三个参数:
1)、协议族,AF_INET - ipv4,AF_INET6 - ipv6等,决定了 socket 的地址类型。
2)、协议类型,SOCK_STREAM - TCP,SOCK_DGRAM - UDP,
3)、协议,一般设为0,会自动与上一个参数对应。
3、connect()
struct sockaddr_in socketAddr;
socketAddr.sin_family = SocketFamily;
socketAddr.sin_port = SocketPort;
struct in_addr socketIn_addr;
socketIn_addr.s_addr = SocketIP;
socketAddr.sin_addr = socketIn_addr;
int result = connect(_socketID, (const struct sockaddr *)&socketAddr, sizeof(socketAddr));
if (result!=0) {
NSLog(@"连接失败");
return;
}
else{
NSLog(@"连接成功");
}
connect() 返回一个 result ,如果为0则说明连接成功,如果不为0则会返回错误码,代表连接失败。
4、recv()
uint8_t buffer[1024];
ssize_t recvLen = recv(self.socketID, buffer, sizeof(buffer), 0);
if (recvLen==0) {
NSLog(@"接受到的数据为空");
return;
}
// 接收到的数据转换
NSData *recvData = [NSData dataWithBytes:buffer length:recvLen];
NSString *recvStr = [[NSString alloc] initWithData:recvData encoding:NSUTF8StringEncoding];
recv(),需要通过循环加载,用于持续接受消息,否则在接受到第一条消息以后会不再接受其他消息。
recv() 不会一直循环,只有在返回数据以后才能往下执行,所以不用担心会死循环。
当返回的长度为0时,一般代表连接失败,就需要注意连接情况了。
5、send()
const char *msg = self.textField.text.UTF8String;
ssize_t sendLen = send(self.socketID, msg, strlen(msg), 0);
if (sendLen <= 0) {
NSLog(@"发送失败");
return;
}
send(),返回一个发送数据的长度,正常情况下会做发送数据的为空判断,所以如果为0,一般代表发送失败。
6、效果
客户端效果
在填上一些其他控件,即可查看效果。
客户端与服务端连接即可进行通信,这里将通信消息展示在客户端上方便调试。
三、服务端
服务端需要用到以下几个方法:
创建socket:socket();
绑定socket:bind();
监听socket:listen();
接受客户端连接:accept();
接受客户端消息:recv();
发送消息:send();
关闭socket:close();
1、头文件及宏
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#define SocketPort htons(8081)
#define SocketIP inet_addr("172.19.203.106")
#define SocketFamily AF_INET //协议族
#define kMaxConnectCount 5
2、socket()
同上
3、bind()
int bind_result = bind(self.serverId, (const struct sockaddr *)&socketAddr, sizeof(socketAddr));
if (bind_result == -1) {
NSLog(@"绑定socket 失败");
return;
}
NSLog(@"绑定socket成功");
4、listen()
int listen_result = listen(self.serverId, kMaxConnectCount);
if (listen_result == -1) {
NSLog(@"监听失败");
return;
}
NSLog(@"监听成功");
5、accept()
struct sockaddr_in client_address;
socklen_t address_len;
// accept函数
int client_socket = accept(self.serverId, (struct sockaddr *)&client_address, &address_len);
self.client_socket = client_socket;
if (client_socket == -1) {
NSLog(@"接受 %u 客户端错误",address_len);
}else{
NSString *acceptInfo = [NSString stringWithFormat:@"客户端 %d 已连接",client_socket];
NSLog(@"%@",acceptInfo);
//开始接受消息
[self receiveMsg];
}
accept() 接受客户端连接,当连接成功以后,可以添加接受消息方法 recv()。
6、recv()
同上
7、send()
同上
8、close()
int close_result = close(self.client_socket);
if (close_result == -1) {
NSLog(@"socket 关闭失败");
return;
}else{
NSLog(@"socket 关闭成功");
}
关闭以后如果需要重新连接,需要客户端服务端都重新连接才可以。
9、效果
服务端效果
服务端与客户端连接以后即可进行通信,这里已经将消息展示在客户端方便调试。
四、其他服务端
1、终端
在终端中输入 nc -lk 8081 ,连接socket即可与客户端进行通信。
效果
2、YMNetwork
在App Store 下载 YMNetwork
YMNetwork 下载
YMNetwork
调试很方便。