TCP 服务端 & UDP
// 包含头文件
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
typedef NS_ENUM (NSInteger,ServerType) {
ServerTypeTCP,
ServerTypeUDP
};
@property (weak, nonatomic) IBOutlet UITextField *desIPTF;
@property (weak, nonatomic) IBOutlet UITextField *desPortTF;
@property (weak, nonatomic) IBOutlet UITextField *locIPTF;
@property (weak, nonatomic) IBOutlet UITextField *locPortTF;
@property (weak, nonatomic) IBOutlet UITextView *recvTextView;
@property (weak, nonatomic) IBOutlet UITextField *sendTF;
@property (nonatomic, assign) int serverSockfd;
@property (nonatomic, assign) int clientSockfd;
@property (nonatomic, assign) int udpSockfd;
@property (nonatomic, assign) ServerType serType;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *ip_addr = [self getIPAddress];
_locIPTF.text = ip_addr;
}
#pragma mark - 创建 TCP 监听
- (IBAction)createdTCPServer:(id)sender {
_desIPTF.enabled = NO;
_desPortTF.enabled = NO;
_locPortTF.enabled = NO;
[NSThread detachNewThreadSelector:@selector(createdTCPSer) toTarget:self withObject:nil];
}
- (void)createdTCPSer {
self.serType = ServerTypeTCP;
BOOL success;
int err;
// 创建 socket
self.serverSockfd = socket(AF_INET, SOCK_STREAM, 0);
success = (self.serverSockfd != -1);
NSString *logStr = nil;
if (success == NO) {
logStr = @"创建 socket 失败...\n";
[self showMessage:logStr];
return;
} else {
logStr = @"创建 socket 成功...\n";
[self showMessage:logStr];
// 本地地址
struct sockaddr_in loc_addr;
memset(&loc_addr, 0, sizeof(loc_addr));
loc_addr.sin_family = AF_INET;
loc_addr.sin_port = htons(_locPortTF.text.intValue);
loc_addr.sin_addr.s_addr = inet_addr(_locIPTF.text.UTF8String);
// 绑定
err = bind(self.serverSockfd, (const struct sockaddr *)&loc_addr, sizeof(loc_addr));
success = (err == 0);
}
if (success == NO) {
logStr = @"socket 绑定失败...\n";
[self showMessage:logStr];
return;
} else {
logStr = @"socket 绑定成功...\n";
[self showMessage:logStr];
// 监听
err = listen(self.serverSockfd, 5); // 5:最大连接个数
success = (err == 0);
}
if (success == NO) {
logStr = @"socket 监听失败...\n";
[self showMessage:logStr];
return;
} else {
logStr = @"socket 监听成功...\n";
[self showMessage:logStr];
while (true) { // 循环
// 连接的客户端的地址
struct sockaddr_in cli_addr;
socklen_t cli_addr_Len = sizeof(cli_addr);
// 接受客户端的请求,并建立连接
self.clientSockfd = accept(self.serverSockfd, (struct sockaddr *)&cli_addr, &cli_addr_Len);
success = (self.clientSockfd != -1);
if (success) {
char *ip_addr = inet_ntoa(cli_addr.sin_addr);
int ip_port = ntohs(cli_addr.sin_port);
dispatch_async(dispatch_get_main_queue(), ^{
_desIPTF.text = [NSString stringWithFormat:@"%s", ip_addr];
_desPortTF.text = [NSString stringWithFormat:@"%d", ip_port];
});
logStr = [NSString stringWithFormat:@"已连接:%s,port:%d\n", ip_addr, ip_port];
[self showMessage:logStr];
char buf[1024];
do {
// 返回读取的字节数
ssize_t recvLen = recv(self.clientSockfd, buf, sizeof(buf), 0);
if (recvLen > 0) {
logStr = [NSString stringWithFormat:@"recv:%@\n", [NSString stringWithUTF8String:buf]];
[self showMessage:logStr];
}
} while (strcmp(buf, "exit") != 0);
}
}
}
}
#pragma mark - 创建 UDP 连接
- (IBAction)connectUDP:(id)sender {
[NSThread detachNewThreadSelector:@selector(connectUDP) toTarget:self withObject:nil];
}
- (void)connectUDP {
self.serType = ServerTypeUDP;
BOOL success;
int err;
// 创建 Socket
self.udpSockfd = socket(AF_INET, SOCK_DGRAM, 0);
success = (self.udpSockfd != -1);
NSString *logStr = nil;
if (success == NO) {
logStr = @"创建 socket 失败...\n";
[self showMessage:logStr];
return;
} else {
logStr = @"创建 socket 成功...\n";
[self showMessage:logStr];
// 本地地址
struct sockaddr_in loc_addr;
bzero(&loc_addr, sizeof(loc_addr));
loc_addr.sin_port = htons(_locPortTF.text.intValue);
loc_addr.sin_addr.s_addr = inet_addr(_locIPTF.text.UTF8String);
// 绑定
err = bind(self.udpSockfd, (const struct sockaddr *)&loc_addr, sizeof(loc_addr));
success = (err == 0);
}
if (success == NO) {
logStr = @"socket 绑定失败...\n";
[self showMessage:logStr];
return;
} else {
logStr = @"socket 绑定成功...\n";
[self showMessage:logStr];
// 目标地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_desPortTF.text.intValue);
des_addr.sin_addr.s_addr = inet_addr(_desIPTF.text.UTF8String);
char buf[256];
bzero(buf, sizeof(buf));
while(1) {
// 接收数据
socklen_t des_addr_len = sizeof(des_addr);
ssize_t recvLen = recvfrom(self.udpSockfd, buf, sizeof(buf), 0, (struct sockaddr*)&des_addr, &des_addr_len);
if (recvLen > 0) {
logStr = [NSString stringWithFormat:@"recv:%@\n", [NSString stringWithUTF8String:buf]];
[self showMessage:logStr];
}
}
}
}
#pragma mark - 发送数据
- (IBAction)btnClick:(id)sender {
if (_sendTF.text.length == 0) {
return;
} else {
ssize_t sendLen;
if (self.serType == ServerTypeTCP) {
// 发送数据
sendLen = send(self.clientSockfd, _sendTF.text.UTF8String, strlen(_sendTF.text.UTF8String), 0);
} else if (self.serType == ServerTypeUDP) {
// 目标地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_desPortTF.text.intValue);
des_addr.sin_addr.s_addr = inet_addr(_desIPTF.text.UTF8String);
// 发送数据
sendLen = sendto(self.udpSockfd, _sendTF.text.UTF8String, strlen(_sendTF.text.UTF8String), 0,
(struct sockaddr *)&des_addr, sizeof(des_addr));
}
if (sendLen > 0) {
NSString *logStr = [NSString stringWithFormat:@"send:%@\n", _sendTF.text];
[self showMessage:logStr];
}
}
}
#pragma mark - 获取本地 IP 地址
- (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
// 显示信息
- (void)showMessage:(NSString *)msg {
dispatch_async(dispatch_get_main_queue(), ^{
_recvTextView.text = [_recvTextView.text stringByAppendingString:msg];
});
}
![Socket7]()
![Socket10]()