iOS

1、BSDSocket

  • 一套 unix 系统下的 socket API(纯 C)。

  • iOS 系统基于 unix,所以支持底层的 BSD Socket,在 Xcode 中可以直接使用。

2、基本使用

2.1 Client 客户端

  • TCP 客户端

    • 包含头文件

      	#import <sys/socket.h>
      	#import <netinet/in.h>
      	#import <arpa/inet.h>
      	#import <ifaddrs.h>
      
    • 创建 Socket

      	// client Socket
      	@property (nonatomic, assign) int clientSocket;
      	
      	self.clientSocket = socket(AF_INET, SOCK_STREAM, 0);
      	    
      	if (self.clientSocket > 0) {
      	    NSLog(@"Socket 创建成功 %d", self.clientSocket);
      	} else {
      	    NSLog(@"Socket 创建失败");
      	}
      
    • 连接到服务器

      	// 创建服务器地址结构体
      	struct sockaddr_in serverAddress;
      	bzero(&serverAddress, sizeof(serverAddress));
      	serverAddress.sin_family      = AF_INET;                        // 协议族
      	serverAddress.sin_port        = htons(12345);                   // 端口 端口数据高位在前低位在后 12345 => 3039 => 3930
      	serverAddress.sin_addr.s_addr = inet_addr("192.168.88.100");    // inet_addr 函数可以把 ip 地址转换成一个整数
      	    
      	int isConnected = connect(self.clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
      	    
      	if (isConnected) {
      	    NSLog(@"连接失败 %d", isConnected);
      	} else {
      	    NSLog(@"连接成功");
      	}
      
    • 发送数据

      	NSString *message = @"你好";
      	    
      	ssize_t sendLen = send(self.clientSocket, message.UTF8String, strlen(message.UTF8String), 0);
      	    
      	if (sendLen > 0) {
      	    NSLog(@"发送成功,发送 %ld 个字节数据", sendLen);
      	} else {
      	    NSLog(@"发送失败 %zd", sendLen);
      	}
      
    • 接收数据

      	// 接收字符串的数组,typedef unsigned char uint8_t;
      	uint8_t buffer[1024];
      	    
      	ssize_t recvLen = recv(self.clientSocket, buffer, sizeof(buffer), 0);
      	    
      	if (recvLen > 0) {
      	    
      	    // 按照服务器返回的长度,从 buffer 中,读取二进制数据,建立 NSData 对象
      	    NSData *data = [NSData dataWithBytes:buffer length:recvLen];
      	    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      	    
      	    NSLog(@"接收成功,接收到 %ld 个字节数据
       接收到:%@", recvLen, str);
      	} else {
      	    NSLog(@"接收失败 %zd", recvLen);
      	}
      
    • 关闭连接

      	// 数据传递完毕之后,关闭连接
      	int isCloseed = close(self.clientSocket);
      	    
      	NSLog(@"%d", isCloseed);
      

2.2 Server 服务端

  • TCP 服务端

    • 包含头文件

      	#import <sys/socket.h>
      	#import <netinet/in.h>
      	#import <arpa/inet.h>
      	#import <ifaddrs.h>
      
    • 创建 Socket

      	// server Socket
      	@property (nonatomic, assign) int serverSocket;
      	
      	// client Socket
      	@property (nonatomic, assign) int clientSocket;
      
      	self.serverSocket = socket(AF_INET, SOCK_STREAM, 0);
      	    
      	if (self.serverSocket > 0) {
      	    NSLog(@"Socket 创建成功 %d", self.serverSocket);
      	} else {
      	    NSLog(@"Socket 创建失败");
      	}
      
    • 开始监听

      	// 创建服务器地址结构体
      	struct sockaddr_in serverAddress;
      	bzero(&serverAddress, sizeof(serverAddress));
      	serverAddress.sin_family      = AF_INET;
      	serverAddress.sin_port        = htons(12345);
      	serverAddress.sin_addr.s_addr = inet_addr("192.168.88.100");
      	    
      	int isBind = bind(self.serverSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
      	    
      	if (isBind) {
      	    NSLog(@"绑定失败 %d", isBind);
      	    return;
      	} else {
      	    NSLog(@"绑定成功");
      	}
      	    
      	int isListen = listen(self.serverSocket, 10);
      	    
      	if (isListen) {
      	    NSLog(@"监听失败 %d", isListen);
      	    return;
      	} else {
      	    NSLog(@"监听成功");
      	}
      	    
      	// clientSocket
      	struct sockaddr_in clientAddress;
      	bzero(&clientAddress, sizeof(clientAddress));
      	socklen_t len = sizeof(clientAddress);
      	
      	self.clientSocket = accept(self.serverSocket, (struct sockaddr *)&clientAddress, &len);
      	    
      	if (self.clientSocket) {
      	    NSLog(@"接收成功 %d,client IP:%zd", self.clientSocket, clientAddress);
      	} else {
      	    NSLog(@"接收失败");
      	}
      
    • 发送数据

      	NSString *message = @"你好";
      	    
      	// 使用 clientSocket
      	ssize_t sendLen = send(self.clientSocket, message.UTF8String, strlen(message.UTF8String), 0);
      	    
      	if (sendLen > 0) {
      	    NSLog(@"发送成功,发送 %ld 个字节数据", sendLen);
      	} else {
      	    NSLog(@"发送失败 %zd", sendLen);
      	}
      
    • 接收数据

      	// 接收字符串的数组,typedef unsigned char uint8_t;
      	uint8_t buffer[1024];
      	    
      	// 使用 clientSocket
      	ssize_t recvLen = recv(self.clientSocket, buffer, sizeof(buffer), 0);
      	    
      	if (recvLen > 0) {
      	    
      	    // 按照服务器返回的长度,从 buffer 中,读取二进制数据,建立 NSData 对象
      	    NSData *data = [NSData dataWithBytes:buffer length:recvLen];
      	    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      	    
      	    NSLog(@"接收成功,接收到 %ld 个字节数据
       接收到:%@", recvLen, str);
      	} else {
      	    NSLog(@"接收失败 %zd", recvLen);
      	}
      
    • 关闭连接

      	// 数据传递完毕之后,关闭连接
      	int isCloseed = close(self.serverSocket);
      	    
      	NSLog(@"%d", isCloseed);
      

3、网络访问

  • 1、请求:

    • 1)请求行

      • GET / HTTP/1.1

      • 方法 GET

      • 路径 /

      • 协议 HTTP 1.1

    • 2)请求头

      • Host: localhost 主机
      • User-Agent: 告诉服务器客户端的类型
      • Accept: 告诉服务器客户端支持的格式
      • Accept-Language: 告诉服务器客户端的语言
      • Accept-Encoding: 告诉服务器客户端支持的压缩格式
  • 2、响应:

    • 1)状态行

      • HTTP/1.1 200 OK

        • 协议 HTTP 1.1
        • 状态码:
          • 200 成功
          • 404 页面没找到
          • 301 内容没变化,用在缓存
    • 2)响应头(主要在开发下载应用的时候使用的)

      • Date: Tue, 24 Mar 2015 01:52:25 GMT 访问日期
      • Server: Apache/2.4.9 (Unix) 访问服务器的类型
      • Content-Location: index.html.en 访问的文件名
      • Content-Length: 45 访问文件的大小
      • Content-Type: text/html 访问文件的类型
    • 3)数据实体

      • <html><body><h1>It works!</h1></body></html>

      • 访问服务器最需的,相当于 NSURLConnection 异步方法回调中的 data。

  • TCP 客户端

    	// 包含头文件
    	#import <sys/socket.h>
    	#import <netinet/in.h>
    	#import <arpa/inet.h>
    	#import <ifaddrs.h>
    	
    	@property (nonatomic, assign) int clientSocket;
    	
    	- (void)socketHttpRequest {
        
        	// 连接到服务器,80 端口 apache 中就是 http 的协议
        	if (![self connection:@"127.0.0.1" port:80]) {                                              
            	return;
        	}
      	
      		// 创建请求
        	NSString *requestStr = @"GET / HTTP/1.1
    "                                                  
        	"Host: localhost
    "
        	"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0
    "
        	"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    "
        	"Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    "
        	
        	// 
     拼接换行,内容由 firefox 浏览器的网络控制面板的原始请求头信息中复制
        	"Accept-Encoding: gzip, deflate
    "                                                          
        	
        	// 删除最后三行,最后一行加两个 
    
    
        	"Connection: keep-alive
    
    ";                                                               
        
        	// 发送接收请求,发送给 web 服务器的请求需要遵守 http 协议
        	NSString *recvStr = [self sendAndRecv:requestStr];                                          
        
        	NSLog(@"%@", recvStr);
    	}
    
    	/// 创建连接
    	- (BOOL)connection:(NSString *)hostText port:(int)port {
        
        	// 创建 Socket
    
            	self.clientSocket = socket(AF_INET, SOCK_STREAM, 0);
        
        	// 连接到服务器
    
            	struct sockaddr_in serverAddress;
            	bzero(&serverAddress, sizeof(serverAddress));
            	serverAddress.sin_family      = AF_INET;
            	serverAddress.sin_port        = htons(port);
            	serverAddress.sin_addr.s_addr = inet_addr(hostText.UTF8String);
    
            	int isConnected = connect(self.clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
        
            	return (isConnected == 0);
    	}
    
    	/// 发送和接收字符串
    	- (NSString *)sendAndRecv:(NSString *)message {
        
        	// 发送数据
    
            	send(self.clientSocket, message.UTF8String, strlen(message.UTF8String), 0);
        
        	// 接收数据
        	
            	uint8_t buffer[1024];                                                                  	
    
            	ssize_t recvLen = recv(self.clientSocket, buffer, sizeof(buffer), 0);
        
            	NSData *data = [NSData dataWithBytes:buffer length:recvLen];                           	
            	NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
            	return str;
    	}
    

4、客户端使用

  • 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 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)connectTCPServer:(id)sender {
    	    
    	    [NSThread detachNewThreadSelector:@selector(connectTCPSer) toTarget:self withObject:nil];
    	}
    	
    	- (void)connectTCPSer {
    	    
    	    self.serType = ServerTypeTCP;
    	    
    	    BOOL success;
    	    int err;
    	    
    	    // 创建 socket
    	    self.clientSockfd = socket(AF_INET, SOCK_STREAM, 0);
    	    success = (self.clientSockfd != -1);
    	    
    	    NSString *logStr = nil;
    	    
    	    if (success == NO) {
    	        
    	        logStr = @"创建 socket 失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"创建 socket 成功...
    ";
    	        [self showMessage:logStr];
    	        
    	        // 服务器地址
    	        struct sockaddr_in ser_addr;
    	        memset(&ser_addr, 0, sizeof(ser_addr));
    	        ser_addr.sin_len         = sizeof(ser_addr);
    	        ser_addr.sin_family      = AF_INET;
    	        ser_addr.sin_port        = htons(_desPortTF.text.intValue);
    	        ser_addr.sin_addr.s_addr = inet_addr(_desIPTF.text.UTF8String);
    	        
    	        // 连接
    	        err = connect(self.clientSockfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
    	        success = (err == 0);
    	    }
    	    
    	    if (success == NO) {
    	        
    	        logStr = @"socket 连接失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = [NSString stringWithFormat:@"socket 连接 %@ 成功...
    ", _desIPTF.text];
    	        [self showMessage:logStr];
    	        
    	        char buf[1024];
    	        do {
    	            // 接收数据
    	            ssize_t recvLen = recv(self.clientSockfd, buf, sizeof(buf), 0);
    	            
    	            if (recvLen > 0) {
    	                logStr = [NSString stringWithFormat:@"recv:%@
    ", [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 失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"创建 socket 成功...
    ";
    	        [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 绑定失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"socket 绑定成功...
    ";
    	        [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:%@
    ", [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:%@
    ", _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];
    	    });
    	}
    

    Socket5 Socket6

5、服务端使用

  • 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 失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"创建 socket 成功...
    ";
    	        [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 绑定失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"socket 绑定成功...
    ";
    	        [self showMessage:logStr];
    	        
    	        // 监听
    	        err = listen(self.serverSockfd, 5);     // 5:最大连接个数
    	        success = (err == 0);
    	    }
    	    
    	    if (success == NO) {
    	        
    	        logStr = @"socket 监听失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"socket 监听成功...
    ";
    	        [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
    ", 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:%@
    ", [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 失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"创建 socket 成功...
    ";
    	        [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 绑定失败...
    ";
    	        [self showMessage:logStr];
    	        
    	        return;
    	        
    	    } else {
    	        
    	        logStr = @"socket 绑定成功...
    ";
    	        [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:%@
    ", [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:%@
    ", _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

原文地址:https://www.cnblogs.com/QianChia/p/6391789.html