You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Mac OS中用Objective-C实现Telnet连接下本地及远端文件展示选择

Objective-C 实现 Telnet 连接下本地+远端文件浏览方案

1 本地 Mac 文件展示实现

本地文件浏览直接使用 Foundation 框架内置的 NSFileManager 即可完成,无需引入额外依赖:

  • 核心调用 contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error: API 遍历指定目录
  • 沙箱权限说明:如果是上架 App Store 的应用,需要在 Signing & Capabilities 中开启对应目录的 File Access 权限,测试阶段可临时关闭沙箱简化调试
  • 示例代码:
NSURL *targetDir = [NSURL fileURLWithPath:NSHomeDirectory()];
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;

// 遍历目录,可通过option参数控制是否展示隐藏文件、是否遍历子目录
NSArray *fileList = [fm contentsOfDirectoryAtURL:targetDir
                       includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey, NSURLFileSizeKey]
                                          options:NSDirectoryEnumerationSkipsHiddenFiles
                                            error:&error];
if (fileList) {
    NSMutableArray *result = [NSMutableArray array];
    for (NSURL *fileURL in fileList) {
        NSString *fileName;
        [fileURL getResourceValue:&fileName forKey:NSURLNameKey error:nil];
        NSNumber *isDirectory;
        [fileURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
        [result addObject:@{
            @"name": fileName,
            @"isDir": isDirectory
        }];
    }
    // 处理result数组渲染UI
} else {
    NSLog(@"读取本地目录失败: %@", error.localizedDescription);
}

2 Telnet 连接与远端文件展示实现

注意:Telnet 协议本身仅提供远程终端交互能力,没有内置文件浏览接口,所有远端文件信息都需要通过执行对应系统的 shell 命令、解析返回结果获取

2.1 核心实现逻辑

  • 建立 TCP 连接到远端设备的 Telnet 端口(默认23)
  • 处理 Telnet 协商选项(终端类型、回声设置等,避免返回内容乱码)
  • 输入远端账号密码完成登录验证
  • 发送对应系统的文件列表命令(Unix/Linux 用 ls -l,Windows 用 dir)
  • 读取命令返回结果,解析为结构化的文件列表

2.2 代码示例

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 建立Telnet TCP连接
- (int)connectToServerWithIP:(NSString *)ip port:(uint16_t)port {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) return -1;
    
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, ip.UTF8String, &serverAddr.sin_addr);
    
    if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
        close(sockfd);
        return -1;
    }
    return sockfd;
}

// 发送命令并读取返回结果
- (NSString *)runCommand:(NSString *)command onSocket:(int)sockfd {
    // 补充换行符模拟终端输入
    NSString *fullCmd = [command stringByAppendingString:@"\n"];
    ssize_t sendLen = send(sockfd, fullCmd.UTF8String, fullCmd.length, 0);
    if (sendLen < 0) return nil;
    
    char buffer[1024];
    NSMutableString *response = [NSMutableString string];
    ssize_t recvLen;
    // 实际使用建议添加超时逻辑,避免长时间阻塞
    while ((recvLen = recv(sockfd, buffer, sizeof(buffer)-1, 0)) > 0) {
        buffer[recvLen] = '\0';
        [response appendString:[NSString stringWithUTF8String:buffer]];
        // 检测到终端提示符则停止读取,可根据远端实际提示符调整匹配规则
        if ([response rangeOfString:@"$ "].location != NSNotFound ||
            [response rangeOfString:@"# "].location != NSNotFound ||
            [response rangeOfString:@"> "].location != NSNotFound) {
            break;
        }
    }
    return response;
}

// 解析ls -l返回结果为文件列表(针对Unix/Linux远端)
- (NSArray *)parseLsOutput:(NSString *)output {
    NSMutableArray *fileList = [NSMutableArray array];
    NSArray *lines = [output componentsSeparatedByCharactersInSet:NSCharacterSet.newlineCharacterSet];
    // 跳过第一行总用量提示
    for (NSInteger i = 1; i < lines.count; i++) {
        NSString *line = lines[i].stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet;
        if (line.length < 10) continue;
        BOOL isDir = [line hasPrefix:@"d"];
        // 按空格拆分字段,过滤空值
        NSArray *components = [line componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceCharacterSet];
        components = [components filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]];
        if (components.count >= 9) {
            // 拼接带空格的文件名
            NSString *fileName = [[components subarrayWithRange:NSMakeRange(8, components.count - 8)] componentsJoinedByString:@" "];
            [fileList addObject:@{@"name":fileName, @"isDir":@(isDir)}];
        }
    }
    return fileList;
}

3 注意事项

  • Telnet 是明文传输协议,账号密码和传输内容都可能被窃听,生产环境建议改用 SSH 协议替代
  • 网络操作不要放在主线程执行,避免阻塞 UI,建议放到 GCD 后台队列处理
  • 不同远端系统的命令返回格式差异较大,需要根据实际测试场景调整解析规则,正则匹配可以提升解析准确率

内容的提问来源于stack exchange,提问作者saravanar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 14:18:03