BSDSocket是UNIX的Socket框架,iOS的系統內核即是UNIX,Xcode能夠直接使用BSDSockethtml
int socket(int domain, int type, int protocol)git
- domain: 協議族,例如:AF_INET(ipv4),AF_INET6(ipv6)
- type:Socket 類型,例如:SOCK_STREAM(流式/TCP),SOCK_DGRAM (數據報式/UDP)
- protocol:指定協議,例如:IPPROTO_TCP(TCP 傳輸協議),IPPROTO_UDP(UDP 傳輸協議),當protocol = 0 時,更加type參數自動選擇類型
- 返回值:若是調用成功就返回新建立的套接字的描述符(大於 0),若是失敗就返回 INVALID_SOCKET(Linux 下失敗返回 -1)
int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen)github
- sockfd :套接字描述符,就是上面socket()的返回值
- addr :是一個 sockaddr 結構指針,該結構中包含了要結合的地址和端口號
- addrlen:addr 的長度
- 返回值:若是函數執行成功,返回值爲 0,不然爲 -1
int listen(int sockfd, int backlog)bash
- sockfd :套接字描述符
- backlog:socket 能夠排隊鏈接的最大數
- 返回值:若是函數執行成功,返回值爲 0,不然爲 -1
int accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen)服務器
- sockfd :監聽套接字描述符
- addr :返回客戶端的地址
- addrlen:addr 的長度
- 返回值:成功返回由內核自動生成的一個全新的描述符(即鏈接成功的客戶端的套接字描述符),失敗返回 -1
int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen)網絡
- sockfd :套接字描述符
- addr :指定數據發送的目的地,也就是服務器端的地址
- addrlen:addr 的長度
- 返回值:若是函數執行成功,返回值爲 0,不然爲 -1
int close(int sockfd)數據結構
- sockfd :套接字描述符
- 返回值:若是函數執行成功,返回值爲 0,不然爲 -1
ssize_t write(int sockfd, const void * buf, size_t size)框架
- sockfd:套接字描述符
- buf :發送內容地址,message.UTF8String 將字符串轉換成 UTF8 的 ASCII 碼,一個漢字須要 3 個字節
- size :發送內容長度,是字節的個數,需使用 strlen() 計算全部字節的長度
- 返回值:若是成功,則返回發送的字節數,失敗則返回 -1,並設置 error 變量。 若是錯誤爲 EINTR 表示在寫的時候出現了中斷錯誤。若是爲 EPIPE 表示網絡鏈接出現了問題(對方已經關閉了鏈接)
ssize_t send(int sockfd, const void * buf, size_t size, int flags)dom
- sockfd:套接字描述符
- buf :發送內容地址,message.UTF8String 將字符串轉換成 UTF8 的 ASCII 碼,一個漢字須要 3 個字節
- size :發送內容長度,是字節的個數,需使用 strlen() 計算全部字節的長度
- 返回值:若是成功,則返回發送的字節數,失敗則返回 -1
ssize_t sendto(int sockfd, const void * buf, size_t size, int flags, const struct sockaddr * dest_addr, socklen_t addrlen)socket
- sockfd :套接字描述符
- buf :待發送數據的緩衝區
- size :緩衝區長度,是字節的個數,需使用 strlen() 計算全部字節的長度
- flags :調用方式標誌位, 通常爲 0, 改變 Flags,將會改變 Sendto 發送的形式
- dest_addr:可選指針,指向目的套接字的地址
- addrlen :dest_addr 的長度
- 返回值:若是成功,則返回發送的字節數,失敗則返回 -1
ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags)
- sockfd:套接字描述符
- msg :送數據的內容
- flags :調用方式標誌位
- 返回值:若是成功,則返回發送的字節數,失敗則返回 -1
ssize_t read(int sockfd, void * buf, size_t size)
- sockfd:套接字描述符
- buf :用於接收數據的緩衝區
- size :緩衝區長度
- 返回值:若是成功,返回實際所讀的字節數,若是返回的值是 0 表示已經讀到文件的結束了,小於 0 表示出現了錯誤。 若是錯誤爲 EINTR 說明讀是由中斷引發的,若是是 ECONNREST 表示網絡鏈接出了問題
ssize_t recv(int sockfd, void * buf, size_t size, int flags)
- sockfd:套接字描述符
- buf :用於接收數據的緩衝區
- size :緩衝區長度
- flags :指定調用方式,MSG_PEEK:查看當前數據,數據將被複制到緩衝區中,但並不從輸入隊列中刪除;MSG_OOB :指示接收到 out-of-band 數據(即須要優先處理的數據)
- 返回值:若是成功,返回實際所讀的字節數,若是返回的值是 0 表示已經讀到文件的結束了,小於 0 表示出現了錯誤
ssize_t recvfrom(int sockfd, void * buf, size_t size, int flags, struct sockaddr * src_addr, socklen_t * addrlen)
ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags)
- sockfd:套接字描述符
- buf :用於接收數據的緩衝區
- size :緩衝區長度
- 返回值: 若是成功,返回實際所讀的字節數,若是返回的值是 0 表示已經讀到文件的結束了,小於 0 表示出現了錯誤
ssize_t recvfrom(int sockfd, void * buf, size_t size, int flags, struct sockaddr * src_addr, socklen_t * addrlen);
- sockfd :套接字描述符
- buf :接收數據緩衝區
- size :緩衝區長度
- flags :調用操做方式。是如下一個或者多個標誌的組合體,可經過 or 操做連在一塊兒: MSG_DONTWAIT:操做不會被阻塞 MSG_ERRQUEUE:指示應該從套接字的錯誤隊列上接收錯誤值,依據不一樣的協議,錯誤值以某種輔佐性消息的方式傳遞進來, 使用者應該提供足夠大的緩衝區。致使錯誤的原封包經過 msg_iovec 做爲通常的數據來傳遞。致使錯誤 的數據報原目標地址做爲 msg_name 被提供。錯誤以 sock_extended_err 結構形態被使用 MSG_PEEK :指示數據接收後,在接收隊列中保留原數據,不將其刪除,隨後的讀操做還能夠接收相同的數據 MSG_TRUNC :返回封包的實際長度,即便它比所提供的緩衝區更長, 只對 packet 套接字有效 MSG_WAITALL :要求阻塞操做,直到請求獲得完整的知足。然而,若是捕捉到信號,錯誤或者鏈接斷開發生,或者下次被 接收的數據類型不一樣,仍會返回少於請求量的數據 MSG_EOR :指示記錄的結束,返回的數據完成一個記錄 MSG_CTRUNC :指明因爲緩衝區空間不足,一些控制數據已被丟棄 MSG_OOB :指示接收到 out-of-band 數據(即須要優先處理的數據) MSG_ERRQUEUE:指示除了來自套接字錯誤隊列的錯誤外,沒有接收到其它數據
- src_addr:可選指針,指向裝有源地址的緩衝區
- addrlen :可選指針,指向 address 緩衝區長度值
- 返回值: 若是成功,返回實際所讀的字節數,若是返回的值是 0 表示已經讀到文件的結束了,小於 0 表示出現了錯誤。
struct sockaddr_in {
__uint8_t sin_len; // 地址長度
sa_family_t sin_family; // IP 地址協議族,必須設爲 AF_INET
in_port_t sin_port; // 通訊端口
struct in_addr sin_addr; // 以網絡字節排序的 4 字節 IPv4 地址
char sin_zero[8]; // 填充項,是爲了讓 sockaddr 與 sockaddr_in 兩個數據結構保持大小相同而保留的空字節
};
struct sockaddr {
__uint8_t sa_len; // 地址長度
sa_family_t sa_family; // IP 地址協議族,必須設爲 AF_INET
char sa_data[14]; // 地址值
};
struct in_addr {
uint32_t s_addr; // 按照網絡字節順序存儲 IP 地址
};
sockaddr_in 和 sockaddr 是並列的結構,指向 sockaddr_in 的結構體的指針也能夠指向 sockaddr 的結構體,並代替它。
也就是說,你可使用 sockaddr_in 創建你所須要的信息。
複製代碼
struct sockaddr_in address;
// 清空內存
memset(&address, 0, sizeof(address)); // 清空指向的內存中的存儲內容,由於分配的內存是隨機的,
// 若是不清空可能會由於垃圾數據產生沒必要要的麻煩
bzero(& address, sizeof(address)); // 清空指向的內存中的存儲內容
// 設置地址值
ser_addr.sin_len = sizeof(address); // 地址長度
address.sin_family = AF_INET; // 協議族
address.sin_port = htons(12345); // 端口數據高位在前低位在後 12345 => 3039 => 3930
address.sin_addr.s_addr = inet_addr("192.168.88.100"); // inet_addr 函數能夠把 ip 地址轉換成一個整數
// 設置全部地址值
address.sin_addr.s_addr = INADDR_ANY; // 指定地址爲 0.0.0.0 的地址,這個地址事實上表示不肯定地址,
// 或全部地址、全部 ip、任意地址。通常來講,在各個系統中均定義成爲 0 值
// 獲取地址值
int ip_port = ntohs(address.sin_port); // 獲取端口,如獲取到:53746
char *ip_addr = inet_ntoa(address.sin_addr); // 獲取 IP 地址,如獲取到:192.168.88.100
// 獲取本地地址
socklen_t addrLen = sizeof(address);
getsockname(self.clientSockfd, (struct sockaddr *)&address, &addrLen);
int ip_port = ntohs(address.sin_port); // 本地端口
char *ip_addr = inet_ntoa(address.sin_addr); // 本地 IP 地址
複製代碼
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
複製代碼
#import "ViewController.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
@interface ViewController ()
{
NSInteger _protocolIndex;//0:TCP,1:UDP
NSString *_loc_ipAdr,*_loc_port,*_des_ipAdress,*_des_port;
int _tcp_serverSockfd,_udp_serverSockfd;//服務端套接字描述符
int _clientSockfd;//客戶端端套接字描述符
int _errCode;//綁定時的返回值
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_loc_ipAdr = @"127.0.0.1";
_loc_port = @"10000";
_des_ipAdress = [self getIPAddress];
_des_port = @"10001";
[NSThread detachNewThreadSelector:@selector(creatTCPSocket) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(creatUDPSocket) toTarget:self withObject:nil];
// Do any additional setup after loading the view.
}
#pragma mark - 建立Socket
- (void)creatTCPSocket{
_tcp_serverSockfd = socket(AF_INET, SOCK_STREAM, 0);
if (_tcp_serverSockfd > 0 ) {
NSLog(@"TCP socket建立成功");
[self TCPBind];
}else {
NSLog(@"TCP socket建立失敗");
}
}
- (void)creatUDPSocket{
_udp_serverSockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (_udp_serverSockfd > 0 ) {
NSLog(@"UDP socket建立成功");
[self UDPBind];
}else {
NSLog(@"UDP socket建立失敗");
}
}
#pragma mark - 綁定IP地址和端口號
- (void)TCPBind {
//獲取本地地址
struct sockaddr_in loc_addr;
//清空指向的內存中的存儲內容,由於分配的內存是隨機的
memset(&loc_addr, 0, sizeof(loc_addr));
// loc_addr.sin_len = sizeof(struct sockaddr_in);
//設置協議族
loc_addr.sin_family = AF_INET;
//設置端口
loc_addr.sin_port = htons(_loc_port.intValue);
//設置IP地址
loc_addr.sin_addr.s_addr = inet_addr(_loc_ipAdr.UTF8String);
//綁定
_errCode = bind(_tcp_serverSockfd, (const struct sockaddr *)&loc_addr,sizeof(loc_addr) );
if (_errCode == 0) {
NSLog(@"TCP socket綁定成功");
[self listen];
}else {
NSLog(@"TCP socekt綁定失敗");
}
}
- (void)UDPBind {
//獲取本地地址
struct sockaddr_in loc_addr;
//清空指向的內存中的存儲內容,由於分配的內存是隨機的
memset(&loc_addr, 0, sizeof(loc_addr));
// loc_addr.sin_len = sizeof(struct sockaddr_in);
//設置協議族
loc_addr.sin_family = AF_INET;
//設置端口
loc_addr.sin_port = htons(_loc_port.intValue);
//設置IP地址
loc_addr.sin_addr.s_addr = inet_addr(_loc_ipAdr.UTF8String);
//綁定
int udpCode = bind(_udp_serverSockfd, (const struct sockaddr *)&loc_addr,sizeof(loc_addr) );
if (udpCode == 0) {
NSLog(@"UDP socket綁定成功");
[self UDPRecv];
}else{
NSLog(@"UDP socekt綁定失敗");
}
}
#pragma mark - 監聽、阻塞等待客服端的鏈接請求、接收消息
- (void)listen {
_errCode = listen(_tcp_serverSockfd, 9);//9:最大鏈接個數
if (_errCode == 0) {
NSLog(@"socket監聽成功");
//使用循環,持續監聽
while (YES) {
//鏈接的客戶端的地址
struct sockaddr_in client_addr;
socklen_t cli_addr_len = sizeof(client_addr);
//阻塞等待客服端的鏈接請求
_clientSockfd = accept(_tcp_serverSockfd, (struct sockaddr *)&client_addr, &cli_addr_len);
if (_clientSockfd != -1) {
//鏈接成功
NSLog(@"socket鏈接成功");
}
//建立一個字符串接收
char buf[1024];
do {
// 返回讀取的字節數
ssize_t recvLen = recv(_clientSockfd, buf, sizeof(buf), 0);
if (recvLen > 0) {
NSString *recvStr = [NSString stringWithFormat:@"[TCP消息][來自客戶端%@:%@]:%@",_des_ipAdress,_des_port, [NSString stringWithUTF8String:buf]];
NSLog(@"%@",recvStr);
dispatch_async(dispatch_get_main_queue(), ^{
self->_recTextView.string = recvStr;
});
}
} while (strcmp(buf, "exit") != 0);
}
}else {
NSLog(@"socekt監聽失敗");
}
}
#pragma mark - UDP接收
- (void)UDPRecv{
// 目標地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_des_port.intValue);
des_addr.sin_addr.s_addr = inet_addr(_des_ipAdress.UTF8String);
char buf[1024];
//清空指向的內存中的存儲內容
bzero(buf, sizeof(buf));
while(1) {
// 接收數據
socklen_t des_addr_len = sizeof(des_addr);
ssize_t recvLen = recvfrom(_udp_serverSockfd, buf, sizeof(buf), 0, (struct sockaddr*)&des_addr, &des_addr_len);
if (recvLen > 0) {
NSString *recvStr = [NSString stringWithFormat:@"[UDP消息][來自客戶端%@:%@]:%@",_des_ipAdress,_des_port, [NSString stringWithUTF8String:buf]];
NSLog(@"%@",recvStr);
dispatch_async(dispatch_get_main_queue(), ^{
self->_recTextView.string = recvStr;
});
}
}
}
#pragma mark - 發送
- (IBAction)sendMsg:(id)sender {
if (!self.textInput.stringValue.length) {
return;
}
NSString *sendMsg = self.textInput.stringValue;
ssize_t sendLen = 0;
if (_protocolIndex == 0) {
// 發送數據
sendLen = send(_clientSockfd, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
}
if (_protocolIndex == 1) {
// 發送數據
// 目標地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_des_port.intValue);
des_addr.sin_addr.s_addr = inet_addr(_des_ipAdress.UTF8String);
// 發送數據
sendLen = sendto(_udp_serverSockfd, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0,
(struct sockaddr *)&des_addr, sizeof(des_addr));
}
if (sendLen > 0) {
NSLog(@"發送成功");
}else{
NSLog(@"發送失敗");
}
}
#pragma mark - 選擇協議
- (IBAction)choseProtocol:(NSComboBox *)sender {
if ([sender.stringValue isEqualToString:@"TCP"]) {
NSLog(@"選擇TCP");
_protocolIndex = 0;
}
if ([sender.stringValue isEqualToString:@"UDP"]) {
NSLog(@"選擇UDP");
_protocolIndex = 1;
}
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#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;
}
複製代碼
#import "ViewController.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
@interface ViewController (){
NSInteger _protocolIndex;//0:TCP,1:UDP
int _tcp_clientSockfd,_udp_clientSockfd;//客戶端端套接字描述符
NSString *_loc_ipAdr,*_loc_port,*_des_ipAdress,*_des_port;
}
@property (weak, nonatomic) IBOutlet UITextField *sendTF;
@property (weak, nonatomic) IBOutlet UITextView *recvTextView;
@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentControl;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_loc_ipAdr = [self getIPAddress];
_loc_port = @"10001";
_des_ipAdress = @"127.0.0.1";
_des_port = @"10000";
[self chose:self.segmentControl];
[NSThread detachNewThreadSelector:@selector(creatTCPSocket) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(creatUDPSocket) toTarget:self withObject:nil];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - 建立Socket
- (void)creatTCPSocket{
_tcp_clientSockfd = socket(AF_INET, SOCK_STREAM, 0);
if (_tcp_clientSockfd > 0 ) {
NSLog(@"TCP socket建立成功");
[self connect];
}else {
NSLog(@"TCP socket建立失敗");
}
}
- (void)creatUDPSocket{
_udp_clientSockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (_udp_clientSockfd > 0 ) {
NSLog(@"UDP socket建立成功");
[self UDPRecv];
}else {
NSLog(@"UDP socket建立失敗");
}
}
#pragma mark - 鏈接服務器
- (void)connect {
//獲取服務器地址
struct sockaddr_in des_addr;
//清空指向的內存中的存儲內容,由於分配的內存是隨機的
memset(&des_addr, 0, sizeof(des_addr));
//設置協議族
des_addr.sin_family = AF_INET;
//設置端口
des_addr.sin_port = htons(_des_port.intValue);
//設置IP地址
des_addr.sin_addr.s_addr = inet_addr(_des_ipAdress.UTF8String);
//鏈接
int errCode = connect(_tcp_clientSockfd, (struct sockaddr *)&des_addr, sizeof(des_addr));
if (errCode == 0) {
NSLog(@"socket鏈接成功");
[self TCPRecv];
}else {
NSLog(@"socekt鏈接失敗");
}
}
#pragma mark - TCP接收
- (void)TCPRecv {
char buf[1024];
do {
// 接收數據
ssize_t recvLen = recv(_tcp_clientSockfd, buf, sizeof(buf), 0);
if (recvLen > 0) {
NSString *recvStr = [NSString stringWithFormat:@"[TCP消息][來自服務端%@:%@]:%@",_des_ipAdress,_des_port, [NSString stringWithUTF8String:buf]];
NSLog(@"%@",recvStr);
dispatch_async(dispatch_get_main_queue(), ^{
self->_recvTextView.text = recvStr;
});
}
} while (strcmp(buf, "exit") != 0);
}
#pragma mark - UDP接收
- (void)UDPRecv {
// 本地地址
struct sockaddr_in loc_addr;
bzero(&loc_addr, sizeof(loc_addr));
loc_addr.sin_port = htons(_loc_port.intValue);
loc_addr.sin_addr.s_addr = inet_addr(_loc_ipAdr.UTF8String);
// 綁定
int err = bind(_udp_clientSockfd, (const struct sockaddr *)&loc_addr, sizeof(loc_addr));
if (err != 0) {
NSLog(@"socket 綁定失敗");
} else {
NSLog(@"socket 綁定成功");
// 目標地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_des_port.intValue);
des_addr.sin_addr.s_addr = inet_addr(_des_ipAdress.UTF8String);
char buf[256];
bzero(buf, sizeof(buf));
while(1) {
// 接收數據
socklen_t des_addr_len = sizeof(des_addr);
ssize_t recvLen = recvfrom(_udp_clientSockfd, buf, sizeof(buf), 0, (struct sockaddr*)&des_addr, &des_addr_len);
if (recvLen > 0) {
NSString *recvStr = [NSString stringWithFormat:@"[UDP消息][來自服務端%@:%@]:%@",_des_ipAdress,_des_port, [NSString stringWithUTF8String:buf]];
NSLog(@"%@",recvStr);
dispatch_async(dispatch_get_main_queue(), ^{
self->_recvTextView.text = recvStr;
});
}
}
}
}
- (IBAction)send:(id)sender {
if (!self.sendTF.text.length) {
return;
}
ssize_t sendLen = 0;
if (_protocolIndex == 0) {
// 發送數據
sendLen = send(_tcp_clientSockfd, _sendTF.text.UTF8String, strlen(_sendTF.text.UTF8String), 0);
}
if (_protocolIndex == 1) {
// 發送數據
// 目標地址
struct sockaddr_in des_addr;
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_port = htons(_des_port.intValue);
des_addr.sin_addr.s_addr = inet_addr(_des_ipAdress.UTF8String);
// 發送數據
sendLen = sendto(_udp_clientSockfd, _sendTF.text.UTF8String, strlen(_sendTF.text.UTF8String), 0,
(struct sockaddr *)&des_addr, sizeof(des_addr));
}
if (sendLen > 0) {
NSLog(@"發送成功");
}else{
NSLog(@"發送失敗");
}
}
- (IBAction)chose:(UISegmentedControl *)sender {
_protocolIndex = sender.selectedSegmentIndex;
if (sender.selectedSegmentIndex == 0) {
NSLog(@"選擇TCP");
}
if (sender.selectedSegmentIndex == 1) {
NSLog(@"選擇UDP");
}
}
#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;
}
@end
複製代碼