AFNetworking 的核心功能是作为 iOS/macOS 客户端库,用于与服务器进行网络通信(发送请求、接收响应),它本身并不是一个像 Apache、Nginx 或 Node.js 那样完整、独立的服务器框架。

AFNetworking 的底层依赖库 AFNetworking 2.x 版本中依赖的 AFNetworking/Serialization 和 AFNetworking/Security 模块,以及其核心的 AFURLSessionManager,确实构建在苹果强大的 NSURLSession 和 Foundation 网络框架之上。
这意味着,我们可以利用 Foundation 框架提供的 NSNetService(用于 Bonjour 服务发现)和 GCD 的网络服务器能力来创建一个简单的、基于 HTTP 的服务器,然后使用 AFNetworking 的工具类来辅助处理请求和序列化响应。
- AFNetworking 不是服务器框架,但我们可以用它来辅助构建一个简单的 HTTP 服务器。
- 对于生产环境,强烈推荐使用成熟的服务器框架,如 Vapor (Swift) 或 Kitura (Swift),或者 Node.js, Python (Django/Flask), Java (Spring) 等。
- 本教程的目标是学习和演示如何在一个 macOS 或 iOS 应用中嵌入一个极简的 HTTP 服务器,并使用 AFNetworking 的组件来处理网络逻辑。
场景:在 macOS App 中创建一个简单的 HTTP 服务器
我们将创建一个 macOS 应用,它启动后会在本地(0.0.1)监听一个端口(8080),并提供一个简单的 API 端点 /hello。

第 1 步:创建 macOS 项目并添加 AFNetworking
- 打开 Xcode,创建一个新的 macOS -> App 项目。
- 使用 CocoaPods 或 Swift Package Manager (SPM) 添加 AFNetworking 依赖,这里以 CocoaPods 为例。
- 在项目根目录创建
Podfile。 - 添加以下内容:
platform :macos, '10.10' target 'YourAppTargetName' do pod 'AFNetworking', '~> 3.2.1' end
- 运行
pod install并打开生成的.xcworkspace文件。
- 在项目根目录创建
第 2 步:创建服务器管理器类
为了更好地组织代码,我们创建一个 ServerManager 类来管理服务器的生命周期。
ServerManager.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ServerManager : NSObject
+ (instancetype)sharedManager;
- (void)startServer;
- (void)stopServer;
@end
NS_ASSUME_NONNULL_END
ServerManager.m
#import "ServerManager.h"
#import <AFNetworking/AFNetworking.h> // 引入 AFNetworking
static const NSInteger kPort = 8080;
@interface ServerManager () <NSNetServiceDelegate, GCDAsyncSocketDelegate>
@property (nonatomic, strong) GCDAsyncSocket *acceptSocket;
@property (nonatomic, strong) NSNetService *netService;
@end
@implementation ServerManager
+ (instancetype)sharedManager {
static ServerManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[ServerManager alloc] init];
});
return sharedInstance;
}
- (void)startServer {
NSLog(@"Starting server on port %ld...", (long)kPort);
// 1. 创建一个 GCDAsyncSocket 来监听连接
self.acceptSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![self.acceptSocket acceptOnPort:kPort error:&error]) {
NSLog(@"Error starting server: %@", error.localizedDescription);
return;
}
NSLog(@"Server started successfully. Listening on port %ld...", (long)kPort);
// 2. (可选) 使用 Bonjour 广播服务,让局域网内的其他设备可以发现
self.netService = [[NSNetService alloc] initWithDomain:@"local." type:@"_http._tcp." name:@"My AFNetworking Server" port:kPort];
self.netService.delegate = self;
[self.netService publish];
}
- (void)stopServer {
NSLog(@"Stopping server...");
[self.acceptSocket disconnect];
self.acceptSocket = nil;
[self.netService stop];
self.netService = nil;
NSLog(@"Server stopped.");
}
#pragma mark - GCDAsyncSocketDelegate
// 当有新的客户端连接时调用
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
NSLog(@"Accepted connection from: %@", newSocket.connectedHost);
// 这里是处理请求的核心逻辑
[self handleRequestFromSocket:newSocket];
}
#pragma mark - Request Handling Logic
// 这里是我们使用 AFNetworking 组件来辅助处理请求的地方
- (void)handleRequestFromSocket:(GCDAsyncSocket *)socket {
// AFHTTPSessionManager 的底层是 NSURLSession,我们可以用它来读取 HTTP 请求流
// 但更简单的方式是直接使用 GCDAsyncSocket 读取数据
// 1. 读取请求数据
[socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
// 2. (在 socket:didReadData:withTag: 回调中处理请求)
// 为了简化,我们直接在这里模拟一个完整的请求读取和处理
// 实际项目中,你需要一个更健壮的状态机来处理分块传输的请求体
// 这里我们假设请求很小,可以一次性读取
// 模拟一个简单的 GET /hello HTTP/1.1 请求
NSString *requestString = @"GET /hello HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";
[socket readDataToData:[requestString dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
}
// 当有数据可读时调用
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSLog(@"Received data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// 3. 解析请求 (简化版)
NSString *requestString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *requestLines = [requestString componentsSeparatedByString:@"\r\n"];
NSArray *requestLineParts = [requestLines[0] componentsSeparatedByString:@" "];
if (requestLineParts.count >= 2) {
NSString *method = requestLineParts[0];
NSString *path = requestLineParts[1];
// 4. 使用 AFNetworking 的序列化工具来构建响应
// 这里我们手动构建一个 JSON 响应
NSDictionary *responseJSON = @{
@"message": @"Hello from AFNetworking Server!",
@"path": path,
@"timestamp": [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterLongStyle]
};
// 使用 AFJSONResponseSerializer 来将字典序列化为 JSON Data
// 这体现了 AFNetworking 作为工具库的用途
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
NSData *responseData = [serializer responseObjectForResponse:nil data:nil error:nil]; // 这种方式不推荐,仅作演示
// 正确的方式是手动序列化
NSError *jsonError;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseJSON options:0 error:&jsonError];
if (jsonError) {
NSLog(@"JSON serialization error: %@", jsonError.localizedDescription);
// 返回 500 错误
NSString *errorResponse = @"HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nError creating JSON response.";
[socket writeData:[errorResponse dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
} else {
// 5. 发送 HTTP 响应
NSString *httpHeader = [NSString stringWithFormat:@"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: %lu\r\n\r\n", (unsigned long)jsonData.length];
NSData *headerData = [httpHeader dataUsingEncoding:NSUTF8StringEncoding];
// 先发送头部,再发送 body
[socket writeData:headerData withTimeout:-1 tag:0];
[socket writeData:jsonData withTimeout:-1 tag:0];
}
}
// 关闭连接
[socket disconnect];
}
#pragma mark - NSNetServiceDelegate
- (void)netServiceDidPublish:(NSNetService *)sender {
NSLog(@"Bonjour service published.");
}
- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary<NSString *, NSNumber *> *)errorDict {
NSLog(@"Failed to publish Bonjour service. Error: %@", errorDict);
}
@end
第 3 步:启动和停止服务器
在 AppDelegate.m 中,我们可以在应用启动时启动服务器,并在应用退出时停止它。

AppDelegate.m
#import "AppDelegate.h"
#import "ServerManager.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// 在应用启动时启动服务器
[[ServerManager sharedManager] startServer];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// 在应用退出前停止服务器
[[ServerManager sharedManager] stopServer];
}
@end
第 4 步:测试服务器
-
在 App 内测试:
- 运行你的 macOS App。
- 打开终端,输入
curl http://127.0.0.1:8080/hello。 - 你应该能看到类似以下的 JSON 输出:
{ "message" : "Hello from AFNetworking Server!", "path" : "/hello", "timestamp" : "10/27/23, 2:30:30 PM" }
-
在浏览器中测试:
- 在浏览器地址栏输入
http://127.0.0.1:8080/hello。 - 浏览器会直接下载一个
hello文件,因为服务器返回的是纯 JSON,如果你想让浏览器直接显示,可以将Content-Type改为text/plain或返回 HTML。
- 在浏览器地址栏输入
-
使用 Bonjour 服务发现:
- 如果你使用了 Bonjour 广播,可以在 macOS 的 "Finder" -> "网络" -> "Bonjour" 看到你的服务 "My AFNetworking Server"。
- 点击它, Finder 会尝试连接,你可以用浏览器访问显示的地址。
AFNetworking 在这个服务器场景中的角色
回顾上面的代码,AFNetworking 并没有直接创建服务器,但它的角色体现在:
-
代码组织与工具化:我们虽然没有直接使用
AFHTTPSessionManager,但引入了 AFNetworking 的头文件,表明我们准备使用它的生态,在更复杂的服务器中,你可以用 AFNetworking 的序列化器(AFJSONResponseSerializer,AFPropertyListResponseSerializer等)来轻松地将对象转换为响应数据,这比自己手写 JSON/XML 要方便和健壮得多。 -
概念借鉴:AFNetworking 的设计理念(如 Delegate 模式、异步处理、基于
NSURLSession)与GCDAsyncSocket的思想是相通的,理解了 AFNetworking 的工作方式,有助于你理解如何构建一个网络服务器。 -
未来扩展:如果你想让这个服务器也支持客户端功能(比如在服务器启动后,自己去请求另一个外部 API),AFNetworking 就能派上大用场了。
结论与建议
- 对于学习:这个例子很好地展示了如何结合 Foundation 的底层网络能力(
GCDAsyncSocket)和 AFNetworking 的工具思想来构建一个简单的服务。 - 对于生产:不要用这种方式来构建生产服务器,它的功能非常有限,没有路由、中间件、模板引擎、数据库集成等现代 Web 框架的核心特性,它对并发连接、安全性、性能等方面的处理也远不如专业框架。
- 推荐方案:
- Swift 后端开发:首选 Vapor 或 Kitura,它们是功能强大、性能优异的 Swift 服务器框架,语法现代,生态完善。
- 其他语言:Node.js (Express/Koa), Python (Django/Flask), Java (Spring Boot), Go (Gin/Beego) 等都是成熟稳定的选择。
希望这个详细的解释和代码示例能帮助你理解 AFNetworking 与服务器之间的关系!
