🎯 Ejemplos recomendados
Balanced sample collections from various categories for you to explore
Ejemplos de Redes macOS Objective-C
Ejemplos de redes macOS Objective-C incluyendo URLSession, solicitudes HTTP, WebSocket y accesibilidad de red
💻 Conceptos Básicos de URLSession objectivec
🟢 simple
⭐⭐⭐
Realizar solicitudes HTTP usando URLSession para descargas de datos, llamadas REST API y cargas de archivos
⏱️ 25 min
🏷️ objectivec, macos, networking, urlsession
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C URLSession Basics
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Simple Data Task
@interface DataTaskDemo : NSObject
+ (void)fetchDataWithURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithURL:url
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Status code: %ld", (long)httpResponse.statusCode);
if (data) {
NSString *responseString = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}];
[task resume];
}
+ (void)synchronousFetchWithURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30.0;
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask *task = [session dataTaskWithURL:url];
[task resume];
// Wait for completion (blocking)
while (task.state == NSURLSessionTaskStateRunning) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
@end
// MARK: - 2. HTTP POST with JSON
@interface JSONPostDemo : NSObject
+ (void)postJSON:(NSDictionary *)jsonDict
toURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// Set headers
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
// Convert JSON to data
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict
options:0
error:&jsonError];
if (jsonError) {
NSLog(@"JSON error: %@", jsonError.localizedDescription);
return;
}
request.HTTPBody = jsonData;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Status code: %ld", (long)httpResponse.statusCode);
if (data) {
NSError *parseError = nil;
id jsonResponse = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&parseError];
if (!parseError) {
NSLog(@"JSON response: %@", jsonResponse);
}
}
}];
[task resume];
}
@end
// MARK: - 3. Download Task
@interface DownloadDemo : NSObject
+ (void)downloadFileFromURL:(NSString *)urlString
toPath:(NSString *)destinationPath {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Download error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Downloaded status: %ld", (long)httpResponse.statusCode);
NSFileManager *fileManager = [NSFileManager defaultManager];
// Remove existing file
if ([fileManager fileExistsAtPath:destinationPath]) {
[fileManager removeItemAtPath:destinationPath error:nil];
}
// Move file to destination
NSError *moveError = nil;
BOOL success = [fileManager moveItemAtPath:location.path
toPath:destinationPath
error:&moveError];
if (success) {
NSLog(@"File saved to: %@", destinationPath);
} else {
NSLog(@"Move error: %@", moveError.localizedDescription);
}
}];
[task resume];
}
+ (void)downloadWithProgress:(NSString *)urlString
toPath:(NSString *)destinationPath {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
// Create download task with progress
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
__block NSURLSessionDownloadTask *weakTask = task;
[task resume];
// Monitor progress (simplified)
NSLog(@"Download started: %@", urlString);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (weakTask.state == NSURLSessionTaskStateRunning) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Downloading...");
}
NSLog(@"Download completed");
});
}
@end
// MARK: - 4. Upload Task
@interface UploadDemo : NSObject
+ (void)uploadFile:(NSString *)filePath
toURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
// Read file data
NSError *readError = nil;
NSData *fileData = [NSData dataWithContentsOfFile:filePath
options:0
error:&readError];
if (readError) {
NSLog(@"File read error: %@", readError.localizedDescription);
return;
}
// Create request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSString *fileName = [filePath lastPathComponent];
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
// Create body
NSMutableData *body = [NSMutableData data];
// Add file data
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:fileData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = body;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request
fromData:body
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Upload error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Upload status: %ld", (long)httpResponse.statusCode);
if (data) {
NSString *responseString = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}];
[task resume];
}
@end
// MARK: - 5. Custom Delegate
@interface SessionDelegate : NSObject <NSURLSessionDataDelegate>
@property (nonatomic, strong) NSMutableData *receivedData;
@property (nonatomic, strong) NSURLResponse *urlResponse;
@end
@implementation SessionDelegate
- (instancetype)init {
self = [super init];
if (self) {
_receivedData = [NSMutableData data];
}
return self;
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
self.urlResponse = response;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Received response: status %ld", (long)httpResponse.statusCode);
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
NSLog(@"Received %lu bytes", (unsigned long)data.length);
}
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
} else {
NSLog(@"Task completed. Total bytes: %lu", (unsigned long)self.receivedData.length);
NSString *responseString = [[NSString alloc] initWithData:self.receivedData
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}
@end
@interface DelegateDemo : NSObject
+ (void)fetchWithDelegate:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
SessionDelegate *delegate = [[SessionDelegate alloc] init];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:delegate
delegateQueue:nil];
NSURLSessionDataTask *task = [session dataTaskWithURL:url];
[task resume];
// Wait for completion
while (task.state == NSURLSessionTaskStateRunning) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
@end
// MARK: - 6. Background Session
@interface BackgroundSessionDemo : NSObject
+ (NSURLSession *)createBackgroundSession {
NSString *identifier = @"com.example.background.session";
NSURLSessionConfiguration *config = [NSURLSessionConfiguration
backgroundSessionConfigurationWithIdentifier:identifier];
config.discretionary = NO;
config.sessionSendsLaunchEvents = YES;
return [NSURLSession sessionWithConfiguration:config];
}
+ (void)startBackgroundDownload:(NSString *)urlString {
NSURLSession *session = [self createBackgroundSession];
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
[task resume];
NSLog(@"Background download started");
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C URLSession Examples ===\n");
// 1. Simple data task
NSLog(@"--- 1. Simple Data Task ---");
[DataTaskDemo fetchDataWithURL:@"https://httpbin.org/get"];
[NSThread sleepForTimeInterval:2.0];
// 2. JSON POST
NSLog(@"\n--- 2. JSON POST ---");
NSDictionary *jsonDict = @{
@"name": @"John Doe",
@"email": @"[email protected]",
@"age": @30
};
[JSONPostDemo postJSON:jsonDict toURL:@"https://httpbin.org/post"];
[NSThread sleepForTimeInterval:2.0];
// 3. Download task
NSLog(@"\n--- 3. Download Task ---");
NSString *downloadPath = @"/tmp/downloaded_file.json";
[DownloadDemo downloadFileFromURL:@"https://httpbin.org/json"
toPath:downloadPath];
[NSThread sleepForTimeInterval:3.0];
// 4. Upload task
NSLog(@"\n--- 4. Upload Task ---");
NSString *testFile = @"/tmp/test_upload.txt";
[@"Test upload content" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[UploadDemo uploadFile:testFile toURL:@"https://httpbin.org/post"];
[NSThread sleepForTimeInterval:2.0];
// 5. Custom delegate
NSLog(@"\n--- 5. Custom Delegate ---");
[DelegateDemo fetchWithDelegate:@"https://httpbin.org/get"];
// 6. Background session
NSLog(@"\n--- 6. Background Session ---");
[BackgroundSessionDemo startBackgroundDownload:@"https://httpbin.org/json"];
[NSThread sleepForTimeInterval:2.0];
NSLog(@"\n=== URLSession Examples Completed ===");
}
return 0;
}
💻 Comunicación WebSocket objectivec
🟡 intermediate
⭐⭐⭐⭐
Implementar comunicación bidireccional en tiempo real usando WebSocket
⏱️ 30 min
🏷️ objectivec, macos, networking, websocket
Prerequisites:
Intermediate Objective-C, Network programming
// macOS Objective-C WebSocket Examples
// Using Foundation and Network framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic WebSocket Client
@interface WebSocketClient : NSObject <NSStreamDelegate>
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, strong) NSOutputStream *outputStream;
@property (nonatomic, strong) NSString *urlString;
@property (nonatomic, assign) BOOL connected;
- (instancetype)initWithURL:(NSString *)urlString;
- (void)connect;
- (void)disconnect;
- (void)sendMessage:(NSString *)message;
@end
@implementation WebSocketClient
- (instancetype)initWithURL:(NSString *)urlString {
self = [super init];
if (self) {
_urlString = urlString;
_connected = NO;
}
return self;
}
- (void)connect {
NSURL *url = [NSURL URLWithString:self.urlString];
if (!url) {
NSLog(@"Invalid URL: %@", self.urlString);
return;
}
NSString *host = url.host;
NSNumber *port = url.port;
if (!port) {
NSString *scheme = url.scheme;
if ([scheme isEqualToString:@"wss"]) {
port = @443;
} else {
port = @80;
}
}
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)host,
[port unsignedShortValue],
&readStream,
&writeStream);
if (!readStream || !writeStream) {
NSLog(@"Failed to create streams");
return;
}
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
self.inputStream.delegate = self;
self.outputStream.delegate = self;
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
NSLog(@"Connecting to %@", self.urlString);
}
- (void)disconnect {
[self.inputStream close];
[self.outputStream close];
[self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
self.inputStream = nil;
self.outputStream = nil;
self.connected = NO;
NSLog(@"Disconnected");
}
- (void)sendMessage:(NSString *)message {
if (!self.connected || !self.outputStream) {
NSLog(@"Not connected");
return;
}
NSString *frame = [NSString stringWithFormat:@"\x00%@\xff", message];
NSData *data = [frame dataUsingEncoding:NSUTF8StringEncoding];
NSInteger written = [self.outputStream write:data.bytes maxLength:data.length];
if (written < 0) {
NSLog(@"Send error");
} else {
NSLog(@"Sent: %@", message);
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted: {
if (stream == self.inputStream) {
self.connected = YES;
// Send WebSocket handshake
NSString *handshake = [NSString stringWithFormat:
@"GET %@ HTTP/1.1\r\n"
@"Host: %@\r\n"
@"Upgrade: websocket\r\n"
@"Connection: Upgrade\r\n"
@"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
@"Sec-WebSocket-Version: 13\r\n"
@"\r\n",
[[NSURL URLWithString:self.urlString] path],
[NSURL URLWithString:self.urlString].host
];
NSData *handshakeData = [handshake dataUsingEncoding:NSUTF8StringEncoding];
[self.outputStream write:handshakeData.bytes maxLength:handshakeData.length];
}
break;
}
case NSStreamEventHasBytesAvailable: {
if (stream == self.inputStream) {
uint8_t buffer[1024];
NSInteger bytesRead = [self.inputStream read:buffer maxLength:sizeof(buffer)];
if (bytesRead > 0) {
NSData *data = [NSData dataWithBytes:buffer length:bytesRead];
// Parse WebSocket frame (simplified)
if (buffer[0] == 0x00) {
NSString *message = [[NSString alloc] initWithBytes:buffer + 1
length:bytesRead - 2
encoding:NSUTF8StringEncoding];
NSLog(@"Received: %@", message);
} else {
NSString *hex = [data description];
NSLog(@"Received data: %@", hex);
}
}
}
break;
}
case NSStreamEventErrorOccurred: {
NSLog(@"Stream error: %@", stream.streamError);
[self disconnect];
break;
}
case NSStreamEventEndEncountered: {
NSLog(@"Stream ended");
[self disconnect];
break;
}
default:
break;
}
}
@end
// MARK: - 2. WebSocket Chat Client
@interface ChatClient : WebSocketClient
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSMutableArray *messages;
- (instancetype)initWithURL:(NSString *)urlString username:(NSString *)username;
- (void)joinChat;
- (void)sendChatMessage:(NSString *)message;
- (void)printMessages;
@end
@implementation ChatClient
- (instancetype)initWithURL:(NSString *)urlString username:(NSString *)username {
self = [super initWithURL:urlString];
if (self) {
_username = username;
_messages = [NSMutableArray array];
}
return self;
}
- (void)joinChat {
[self connect];
// Send join message
NSString *joinMsg = [NSString stringWithFormat:@"/join %@", self.username];
[self sendMessage:joinMsg];
}
- (void)sendChatMessage:(NSString *)message {
NSString *chatMsg = [NSString stringWithFormat:@"/msg %@", message];
[self sendMessage:chatMsg];
[self.messages addObject:[NSString stringWithFormat:@"%@: %@", self.username, message]];
}
- (void)printMessages {
NSLog(@"\n=== Chat Messages ===");
for (NSString *msg in self.messages) {
NSLog(@"%@", msg);
}
NSLog(@"==================\n");
}
@end
// MARK: - 3. Reconnection Handler
@interface ResilientWebSocketClient : WebSocketClient
@property (nonatomic, assign) NSInteger maxRetries;
@property (nonatomic, assign) NSInteger currentRetry;
@property (nonatomic, assign) NSTimeInterval retryDelay;
- (void)autoConnectWithRetries:(NSInteger)maxRetries delay:(NSTimeInterval)delay;
@end
@implementation ResilientWebSocketClient
- (void)autoConnectWithRetries:(NSInteger)maxRetries delay:(NSTimeInterval)delay {
self.maxRetries = maxRetries;
self.retryDelay = delay;
self.currentRetry = 0;
[self attemptConnect];
}
- (void)attemptConnect {
[self connect];
// Check connection after delay
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.retryDelay * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
if (!self.connected && self.currentRetry < self.maxRetries) {
self.currentRetry++;
NSLog(@"Connection failed. Retrying (%ld/%ld)...",
(long)self.currentRetry, (long)self.maxRetries);
[self attemptConnect];
} else if (!self.connected) {
NSLog(@"Max retries reached. Connection failed.");
}
});
}
@end
// MARK: - 4. Heartbeat Protocol
@interface HeartbeatWebSocketClient : WebSocketClient
@property (nonatomic, strong) NSTimer *heartbeatTimer;
@property (nonatomic, assign) NSTimeInterval heartbeatInterval;
- (void)startHeartbeat:(NSTimeInterval)interval;
- (void)stopHeartbeat;
@end
@implementation HeartbeatWebSocketClient
- (void)startHeartbeat:(NSTimeInterval)interval {
self.heartbeatInterval = interval;
self.heartbeatTimer = [NSTimer scheduledTimerWithTimeInterval:interval
repeats:YES
block:^(NSTimer *timer) {
[self sendMessage:@"/ping"];
NSLog(@"Sent heartbeat");
}];
NSLog(@"Heartbeat started (%.0f seconds)", interval);
}
- (void)stopHeartbeat {
[self.heartbeatTimer invalidate];
self.heartbeatTimer = nil;
NSLog(@"Heartbeat stopped");
}
- (void)disconnect {
[self stopHeartbeat];
[super disconnect];
}
@end
// MARK: - 5. Message Queue
@interface MessageQueueWebSocketClient : WebSocketClient
@property (nonatomic, strong) NSMutableArray *messageQueue;
@property (nonatomic, assign) BOOL shouldQueueMessages;
- (instancetype)initWithURL:(NSString *)urlString;
@end
@implementation MessageQueueWebSocketClient
- (instancetype)initWithURL:(NSString *)urlString {
self = [super initWithURL:urlString];
if (self) {
_messageQueue = [NSMutableArray array];
_shouldQueueMessages = YES;
}
return self;
}
- (void)sendMessage:(NSString *)message {
if (self.connected) {
[super sendMessage:message];
} else if (self.shouldQueueMessages) {
[self.messageQueue addObject:message];
NSLog(@"Queued message: %@ (queue size: %lu)",
message, (unsigned long)self.messageQueue.count);
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
[super stream:stream handleEvent:eventCode];
if (eventCode == NSStreamEventOpenCompleted && stream == self.inputStream) {
// Send queued messages
if (self.messageQueue.count > 0) {
NSLog(@"Sending %lu queued messages", (unsigned long)self.messageQueue.count);
for (NSString *queuedMessage in [self.messageQueue copy]) {
[super sendMessage:queuedMessage];
[self.messageQueue removeObject:queuedMessage];
}
}
}
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C WebSocket Examples ===\n");
// 1. Basic WebSocket client
NSLog(@"--- 1. Basic WebSocket Client ---");
WebSocketClient *client = [[WebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
[client connect];
[NSThread sleepForTimeInterval:1.0];
[client sendMessage:@"Hello, WebSocket!"];
[client sendMessage:@"How are you?"];
[NSThread sleepForTimeInterval:2.0];
[client disconnect];
// 2. Chat client
NSLog(@"\n--- 2. Chat Client ---");
ChatClient *chatClient = [[ChatClient alloc]
initWithURL:@"ws://echo.websocket.org"
username:@"Alice"];
[chatClient joinChat];
[NSThread sleepForTimeInterval:1.0];
[chatClient sendChatMessage:@"Hi everyone!"];
[chatClient sendChatMessage:@"How's it going?"];
[NSThread sleepForTimeInterval:2.0];
[chatClient printMessages];
[chatClient disconnect];
// 3. Resilient client with retries
NSLog(@"\n--- 3. Resilient Client ---");
ResilientWebSocketClient *resilientClient = [[ResilientWebSocketClient alloc]
initWithURL:@"ws://invalid.websocket.org"];
[resilientClient autoConnectWithRetries:3 delay:1.0];
[NSThread sleepForTimeInterval:5.0);
// 4. Heartbeat
NSLog(@"\n--- 4. Heartbeat Protocol ---");
HeartbeatWebSocketClient *heartbeatClient = [[HeartbeatWebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
[heartbeatClient connect];
[NSThread sleepForTimeInterval:1.0];
[heartbeatClient startHeartbeat:2.0];
[NSThread sleepForTimeInterval:8.0);
[heartbeatClient stopHeartbeat];
[heartbeatClient disconnect];
// 5. Message queue
NSLog(@"\n--- 5. Message Queue ---");
MessageQueueWebSocketClient *queueClient = [[MessageQueueWebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
// Send messages before connected
[queueClient sendMessage:@"Queued 1"];
[queueClient sendMessage:@"Queued 2"];
[queueClient sendMessage:@"Queued 3"];
[queueClient connect];
[NSThread sleepForTimeInterval:2.0);
[queueClient sendMessage:@"After connect"];
[NSThread sleepForTimeInterval:2.0];
[queueClient disconnect];
NSLog(@"\n=== WebSocket Examples Completed ===");
}
return 0;
}
💻 Accesibilidad de Red objectivec
🟡 intermediate
⭐⭐⭐
Monitorear el estado de conectividad de red y detectar cambios de red
⏱️ 25 min
🏷️ objectivec, macos, networking, reachability
Prerequisites:
Intermediate Objective-C, SystemConfiguration framework
// macOS Objective-C Network Reachability Examples
// Using SystemConfiguration framework
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
// MARK: - 1. Basic Reachability Check
@interface ReachabilityChecker : NSObject
+ (BOOL)isNetworkAvailable {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
if (!reachability) {
return NO;
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return NO;
}
BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
return isReachable && !needsConnection;
}
+ (NSString *)getConnectionType {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
if (!reachability) {
return @"Unknown";
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return @"Unknown";
}
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) {
return @"No Connection";
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
return @"Cellular";
}
return @"WiFi";
}
@end
// MARK: - 2. Reachability Monitor
@interface ReachabilityMonitor : NSObject
@property (nonatomic, assign) SCNetworkReachabilityRef reachability;
@property (nonatomic, strong) NSTimer *pollingTimer;
@property (nonatomic, copy) void (^onChange)(BOOL isReachable, NSString *connectionType);
- (instancetype)initWithCallback:(void (^)(BOOL, NSString *))callback;
- (void)startMonitoring;
- (void)stopMonitoring;
@end
@implementation ReachabilityMonitor
- (instancetype)initWithCallback:(void (^)(BOOL, NSString *))callback {
self = [super init];
if (self) {
_onChange = callback;
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
_reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault,
(struct sockaddr *)&zeroAddress);
}
return self;
}
- (void)startMonitoring {
if (!_reachability) {
NSLog(@"Reachability not initialized");
return;
}
// Start polling timer
self.pollingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
repeats:YES
block:^(NSTimer *timer) {
BOOL isReachable = [ReachabilityChecker isNetworkAvailable];
NSString *connectionType = [ReachabilityChecker getConnectionType];
if (self.onChange) {
self.onChange(isReachable, connectionType);
}
}];
NSLog(@"Started monitoring network reachability");
}
- (void)stopMonitoring {
[self.pollingTimer invalidate];
self.pollingTimer = nil;
NSLog(@"Stopped monitoring network reachability");
}
- (void)dealloc {
[self stopMonitoring];
if (_reachability) {
CFRelease(_reachability);
}
}
@end
// MARK: - 3. Host Reachability
@interface HostReachabilityChecker : NSObject
+ (BOOL)isHostReachable:(NSString *)hostName;
+ (BOOL)isHostReachableSync:(NSString *)hostName;
@end
@implementation HostReachabilityChecker
+ (BOOL)isHostReachable:(NSString *)hostName {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault,
[hostName UTF8String]);
if (!reachability) {
return NO;
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return NO;
}
BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
return isReachable && !needsConnection;
}
+ (BOOL)isHostReachableSync:(NSString *)hostName {
// Try to actually connect to the host
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)hostName,
80,
&readStream,
&writeStream);
if (!readStream || !writeStream) {
return NO;
}
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
// Wait for connection
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:3.0];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
BOOL reachable = [outputStream streamStatus] == NSStreamStatusOpen;
[inputStream close];
[outputStream close];
return reachable;
}
@end
// MARK: - 4. Connection Quality
@interface ConnectionQuality : NSObject
+ (NSString *)assessConnectionQuality {
// Simple quality assessment based on connection type
NSString *connectionType = [ReachabilityChecker getConnectionType];
if ([connectionType isEqualToString:@"No Connection"]) {
return @"None";
} else if ([connectionType isEqualToString:@"WiFi"]) {
return @"Good";
} else if ([connectionType isEqualToString:@"Cellular"]) {
return @"Moderate";
}
return @"Unknown";
}
+ (void)runSpeedTest:(void (^)(double speedMbps))completion {
// Simulated speed test
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:@"https://httpbin.org/bytes/1048576"];
NSData *data = [NSData dataWithContentsOfURL:url];
double speedMbps = 0;
if (data) {
// Assume it took 2 seconds for 1 MB
double mb = data.length / (1024.0 * 1024.0);
speedMbps = mb / 2.0;
}
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(speedMbps);
}
});
});
}
@end
// MARK: - 5. Network State Manager
@interface NetworkStateManager : NSObject
@property (nonatomic, assign) BOOL isReachable;
@property (nonatomic, strong) NSString *connectionType;
@property (nonatomic, strong) NSMutableArray<void (^)(BOOL, NSString *)> *observers;
+ (instancetype)sharedManager;
- (void)addObserver:(void (^)(BOOL, NSString *))observer;
- (void)removeObserver:(void (^)(BOOL, NSString *))observer;
- (void)startMonitoring;
- (void)stopMonitoring;
@end
@implementation NetworkStateManager {
ReachabilityMonitor *_monitor;
}
+ (instancetype)sharedManager {
static NetworkStateManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[NetworkStateManager alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_isReachable = [ReachabilityChecker isNetworkAvailable];
_connectionType = [ReachabilityChecker getConnectionType];
_observers = [NSMutableArray array];
__weak typeof(self) weakSelf = self;
_monitor = [[ReachabilityMonitor alloc] initWithCallback:^(BOOL isReachable, NSString *connectionType) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.isReachable != isReachable ||
![strongSelf.connectionType isEqualToString:connectionType]) {
strongSelf.isReachable = isReachable;
strongSelf.connectionType = connectionType;
NSLog(@"Network changed: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
[strongSelf notifyObservers];
}
}];
}
return self;
}
- (void)addObserver:(void (^)(BOOL, NSString *))observer {
[self.observers addObject:observer];
// Immediately call with current state
observer(self.isReachable, self.connectionType);
}
- (void)removeObserver:(void (^)(BOOL, NSString *))observer {
[self.observers removeObject:observer];
}
- (void)notifyObservers {
for (void (^observer)(BOOL, NSString *) in self.observers) {
observer(self.isReachable, self.connectionType);
}
}
- (void)startMonitoring {
[_monitor startMonitoring];
}
- (void)stopMonitoring {
[_monitor stopMonitoring];
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Network Reachability Examples ===\n");
// 1. Basic reachability check
NSLog(@"--- 1. Basic Reachability Check ---");
BOOL isAvailable = [ReachabilityChecker isNetworkAvailable];
NSString *connType = [ReachabilityChecker getConnectionType];
NSLog(@"Network Available: %@", isAvailable ? @"YES" : @"NO");
NSLog(@"Connection Type: %@", connType);
// 2. Host reachability
NSLog(@"\n--- 2. Host Reachability ---");
NSArray *hosts = @[@"apple.com", @"google.com", @"github.com", @"localhost"];
for (NSString *host in hosts) {
BOOL reachable = [HostReachabilityChecker isHostReachable:host];
NSLog(@"%@: %@", host, reachable ? @"✓ Reachable" : @"✗ Unreachable");
}
// 3. Connection quality
NSLog(@"\n--- 3. Connection Quality ---");
NSString *quality = [ConnectionQuality assessConnectionQuality];
NSLog(@"Connection Quality: %@", quality);
[ConnectionQuality runSpeedTest:^(double speedMbps) {
NSLog(@"Speed: %.2f Mbps", speedMbps);
}];
[NSThread sleepForTimeInterval:5.0];
// 4. Reachability monitor
NSLog(@"\n--- 4. Reachability Monitor ---");
ReachabilityMonitor *monitor = [[ReachabilityMonitor alloc]
initWithCallback:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Status: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
}];
[monitor startMonitoring];
NSLog(@"Monitoring for 15 seconds...");
[NSThread sleepForTimeInterval:15.0];
[monitor stopMonitoring];
// 5. Network state manager
NSLog(@"\n--- 5. Network State Manager ---");
NetworkStateManager *manager = [NetworkStateManager sharedManager];
[manager addObserver:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Observer 1: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
}];
[manager addObserver:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Observer 2: Quality = %@", [ConnectionQuality assessConnectionQuality]);
}];
[manager startMonitoring];
NSLog(@"State manager monitoring for 10 seconds...");
[NSThread sleepForTimeInterval:10.0];
[manager stopMonitoring];
NSLog(@"\n=== Network Reachability Examples Completed ===");
}
return 0;
}