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

目录
相关文章
|
2月前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
106 3
|
4月前
|
存储 iOS开发
iOS 开发,如何进行应用的本地化(Localization)?
iOS 开发,如何进行应用的本地化(Localization)?
123 2
|
4月前
|
存储 数据建模 数据库
IOS开发数据存储:什么是 UserDefaults?有哪些替代方案?
IOS开发数据存储:什么是 UserDefaults?有哪些替代方案?
42 0
|
4月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
106 2
|
2月前
|
API 开发工具 Android开发
iOS 和 Android 平台的开发有哪些主要区别?
iOS与Android开发区别:iOS用Objective-C/Swift,App Store唯一下载渠道;Android用Java/Kotlin,多商店发布(如Google Play、华为市场)。设计上,iOS简洁一致,Android灵活可定制。开发工具,iOS用Xcode,Android用Android Studio。硬件和系统多样性,iOS统一,Android复杂。权限管理、审核流程及API各有特点,开发者需依据目标平台特性进行选择。
38 3
|
12天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
12天前
|
存储 Swift iOS开发
使用Swift开发一个简单的iOS应用的详细步骤。
使用Swift开发iOS应用的步骤包括:创建Xcode项目,设计界面(Storyboard或代码),定义数据模型,实现业务逻辑,连接界面和逻辑,处理数据存储(如Core Data),添加网络请求(必要时),调试与测试,根据测试结果优化改进,最后提交至App Store或其它平台发布。
32 0
|
12天前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 与 UIKit:构建 iOS 应用界面
【4月更文挑战第30天】本文探讨了Swift和UIKit在构建iOS应用界面的关键技术和实践方法。Swift的简洁语法、类型安全和高效编程模型,加上与UIKit的紧密集成,使开发者能便捷地创建用户界面。UIKit提供视图、控制器、布局、动画和事件处理等功能,支持灵活的界面设计。实践中,遵循设计原则,合理组织视图层次,运用布局和动画,以及实现响应式设计,能提升界面质量和用户体验。文章通过登录、列表和详情界面的实际案例展示了Swift与UIKit的结合应用。
|
12天前
|
存储 安全 Swift
【Swift 开发专栏】使用 Swift 开发一个简单的 iOS 应用
【4月更文挑战第30天】本文介绍了使用 Swift 开发简单 iOS 待办事项应用的步骤。首先,阐述了 iOS 开发的吸引力及 Swift 语言的优势。接着,详细说明了应用的需求和设计,包括添加、查看和删除待办事项的功能。开发步骤包括创建项目、界面搭建、数据存储、功能实现,并提供了相关代码示例。最后,强调了实际开发中需注意的细节和优化,旨在帮助初学者掌握 Swift 和 iOS 开发基础。