iOS - BSDSocket 的使用

简介: 1、BSDSocket一套 unix 系统下的 socket API(纯 C)。iOS 系统基于 unix,所以支持底层的 BSD Socket,在 Xcode 中可以直接使用。2、基本使用2.

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 个字节数据\n 接收到:%@", 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 个字节数据\n 接收到:%@", 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\n"                                                  
            "Host: localhost\n"
            "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0\n"
            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
            "Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\n"
    
            // \n 拼接换行,内容由 firefox 浏览器的网络控制面板的原始请求头信息中复制
            "Accept-Encoding: gzip, deflate\n"                                                          
    
            // 删除最后三行,最后一行加两个 \n\n
            "Connection: keep-alive\n\n";                                                               
    
            // 发送接收请求,发送给 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 失败...\n";
                [self showMessage:logStr];
    
                return;
    
            } else {
    
                logStr = @"创建 socket 成功...\n";
                [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 连接失败...\n";
                [self showMessage:logStr];
    
                return;
    
            } else {
    
                logStr = [NSString stringWithFormat:@"socket 连接 %@ 成功...\n", _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:%@\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];
            });
        }

    Socket5Socket6

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 失败...\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];
            });
        }

    Socket7Socket10

目录
相关文章
|
3天前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。
|
4天前
|
搜索推荐 IDE API
打造个性化天气应用:iOS开发之旅
【9月更文挑战第35天】在这篇文章中,我们将一起踏上iOS开发的旅程,通过创建一个个性化的天气应用来探索Swift编程语言的魅力和iOS平台的强大功能。无论你是编程新手还是希望扩展你的技能集,这个项目都将为你提供实战经验,帮助你理解从构思到实现一个应用的全过程。让我们开始吧,构建你自己的天气应用,探索更多可能!
21 1
|
12天前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
21天前
|
开发框架 数据可视化 Java
iOS开发-SwiftUI简介
iOS开发-SwiftUI简介
|
9天前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
33 7
|
12天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台解决方案
【9月更文挑战第27天】在移动应用开发的广阔天地中,安卓和iOS两大操作系统如同双子星座般耀眼。开发者们在这两大平台上追逐着创新的梦想,却也面临着选择的难题。如何在保持高效的同时,实现跨平台的开发?本文将带你探索跨平台开发的魅力所在,揭示其背后的技术原理,并通过实际案例展示其应用场景。无论你是安卓的忠实拥趸,还是iOS的狂热粉丝,这篇文章都将为你打开一扇通往跨平台开发新世界的大门。
|
18天前
|
前端开发 iOS开发 开发者
探索iOS开发中的SwiftUI框架
【9月更文挑战第21天】在iOS应用开发的广阔天地中,SwiftUI框架如一股清新之风,为开发者带来了声明式语法的便捷与高效。本文将深入探讨SwiftUI的核心概念、布局方式及数据绑定机制,同时通过实例演示如何运用SwiftUI构建用户界面,旨在引领读者领略SwiftUI的魅力,并激发其对iOS开发新趋势的思考与实践。
34 6
|
18天前
|
安全 Swift iOS开发
探索iOS开发之旅:Swift语言的魅力与挑战
【9月更文挑战第21天】在这篇文章中,我们将一起潜入iOS开发的海洋,探索Swift这门现代编程语言的独特之处。从简洁的语法到强大的功能,Swift旨在让开发者能够以更高效、更安全的方式构建应用程序。通过实际代码示例,我们会深入了解Swift如何简化复杂任务,并讨论它面临的挑战和未来的发展方向。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和知识。
32 4
|
29天前
|
IDE 开发工具 Android开发
安卓与iOS开发对比:平台选择对项目成功的影响
【9月更文挑战第10天】在移动应用开发的世界中,选择正确的平台是至关重要的。本文将深入探讨安卓和iOS这两大主要移动操作系统的开发环境,通过比较它们的市场份额、开发工具、编程语言和用户群体等方面,为开发者提供一个清晰的指南。我们将分析这两个平台的优势和劣势,并讨论如何根据项目需求和目标受众来做出最佳选择。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更好地理解每个平台的特性,并指导你做出明智的决策。