zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JavaScript中的prototype
    SQL 时间格式转换
    ASP.NET MVC自定义视图引擎ViewEngine 创建Model的专属视图
    JavaScript事件使用指南
    30行代码实现JavaScript中的MVC
    JavaScript中this指针指向的彻底理解
    JavaScript 中的命名空间
    C#嵌套类型
    C# 为枚举创建新方法
    Lambda 表达式
  • 原文地址:https://www.cnblogs.com/QianChia/p/6391789.html
Copyright © 2011-2022 走看看