2009-04-11 18 views
9

Tengo un daemon ejecutándose en un servidor que está enganchado a un puerto TCP/IP. Estoy buscando para ver si hay compatibilidad con marcos de iPhone/Cocoa-touch que dan un buen contenedor OO para hablar con el daemon sobre un socket IP. Necesito poder consultar interactivamente el daemon con comandos y recuperar información.Marco Cocoa-Touch para hablar con un socket TCP?

Si no hay envoltorios OO para una tarea así, ¿cuál es la siguiente mejor opción?

Respuesta

6

En términos generales, subiendo la pila tiene:

  • sockets BSD
  • CFSocket
  • CFReadStream/CFWriteStream/NSInputStream/NSOutputStream
  • CFHTTPStream
  • NSURLConnection

Parece que quieres CFSocket, o posiblemente CFStream.

15
+0

¿Está desactualizado? Intenté usarlo en Xcode 4, pero tuve 17 problemas con solo agregar las clases en el proyecto. – Rihards

+2

@Richards No, todavía se mantiene activamente en https://github.com/robbiehanson/CocoaAsyncSocket –

+0

Gracias, parece que funciona ahora. – Rihards

13

Aquí hay un código de muestra del código AsyncSocket anteriormente mencionado que modifiqué en una clase llamada SocketCommunicationManager.

Algunas cosas a tener en cuenta:

  • Nuestros mensajes se están delimitadas con caracteres de nueva línea (\ n) por lo que al leer los datos de la toma que tenía que asegurarse de utilizar la constante de la derecha desde la clase AsyncSocket (LFData en nuestro caso). AsyncSocket también proporciona CRLFData, CRData y ZeroData como delimitadores de mensaje predefinidos.
  • Configuré el SocketCommunicationManager para esperar siempre un mensaje entrante después de que recibí y actué en uno anterior. Para lograr eso utilicé el método (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag. Este método esperará hasta que los datos se escriban en el socket, se leerán hasta el delimitador especificado y luego se llamará al método de delegado (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
  • El SocketCommunicationManager utiliza NSNotificationCenter para publicar cualquier mensaje recibido del socket. Estos mensajes se denominan kNotification y el mensaje se coloca en el diccionario userInfo utilizando la clave kNotificationMessage.
  • Todo lo leído desde el socket está envuelto en un objeto NSData, por lo que deberá decodificar esos datos una vez que se hayan recibido.

Aquí está el código:

#import <Foundation/Foundation.h> 

extern NSString * const kNotification; 
extern NSString * const kNotificationMessage; 

@class AsyncSocket; 

@interface SocketCommunicationManager : NSObject { 
    AsyncSocket *socket; 
    BOOL isRunning; 
    NSNotificationCenter* notificationCenter; 
} 

@property (readwrite, assign) BOOL isRunning; 

- (void)connectToHost:(NSString *)hostName onPort:(int)port; 
- (void)sendMessage:(NSString *)message; 
- (void)disconnect; 

@end 


#import "SocketCommunicationManager.h" 
#import "AsyncSocket.h" 

NSString * const kNotification = @"kNotification"; 
NSString * const kNotificationMessage = @"kNotificationMessage"; 

@implementation SocketCommunicationManager 

@synthesize isRunning; 

- (id) init { 
    if (!(self = [super init])) 
     return nil; 

    socket = [[AsyncSocket alloc] initWithDelegate:self]; 
    [self setIsRunning:NO]; 
    notificationCenter = [NSNotificationCenter defaultCenter]; 

    return self; 
} 

- (void)connectToHost:(NSString *)hostName onPort:(int)port { 
    if (![self isRunning]) { 
     if (port < 0 || port > 65535) 
      port = 0; 

     NSError *error = nil; 
     if (![socket connectToHost:hostName onPort:port error:&error]) { 
      NSLog(@"Error connecting to server: %@", error); 
      return; 
     } 

     [self setIsRunning:YES]; 
    } else { 
     [socket disconnect]; 
     [self setIsRunning:false]; 
    } 
} 

- (void)disconnect { 
    [socket disconnect]; 
} 

- (void)dealloc { 
    [super dealloc]; 
    [socket disconnect]; 
    [socket dealloc]; 
} 

- (void)sendMessage:(NSString *)message { 
    NSString *terminatedMessage = [message stringByAppendingString:@"\r\n"]; 
    NSData *terminatedMessageData = [terminatedMessage dataUsingEncoding:NSASCIIStringEncoding]; 
    [socket writeData:terminatedMessageData withTimeout:-1 tag:0]; 
} 

#pragma mark AsyncSocket Delegate 

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port { 
    NSLog(@"Connected to server %@:%hu", host, port); 
    [sock readDataToData:[AsyncSocket LFData] withTimeout:-1 tag:0]; 
} 

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 
    NSData *truncatedData = [data subdataWithRange:NSMakeRange(0, [data length] - 1)]; 
    NSString *message = [[[NSString alloc] initWithData:truncatedData encoding:NSASCIIStringEncoding] autorelease]; 

    if (message) 
     NSLog(@"%@", message); 
    else 
     NSLog(@"Error converting received data into UTF-8 String"); 

    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message forKey:kNotificationMessage]; 
    [notificationCenter postNotificationName:kNotification object:self userInfo:userInfo]; 

    [sock readDataToData:[AsyncSocket LFData] withTimeout:-1 tag:0]; 
} 

- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag { 
    [sock readDataToData:[AsyncSocket LFData] withTimeout:-1 tag:0]; 
} 

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err { 
    NSLog(@"Client Disconnected: %@:%hu", [sock connectedHost], [sock connectedPort]); 
} 


@end 
Cuestiones relacionadas