2009-09-17 24 views
20

He leído un montón de preguntas acerca de este tema en este sitio web sin embargo, no respondió a mi pregunta tranquila. Si no puede ser ### sobre mi objetivo o fondo, salte a la pregunta.iPhone Socket TCP/IP del servidor/cliente

Mi meta

es construir un servidor que puede ejecutar en Mac OS X 10.4 o superior y más tarde, portarlo a Windows XP/Vista (ni idea de cómo hacer eso todavía, pero eso es un problema Para luego).

luego dejar que el iPhone sea el cliente que es capaz de ver los nombres de los equipos que ejecutan el servidor (a través de Wi-Fi). El usuario del iPhone puede seleccionar el nombre de la computadora para conectarse al servidor en esa computadora.

Después de que pueden enviar mensajes de texto simples entre sí. Por ejemplo, el iPhone envía 'Knock Knock' y el servidor responde '¿Quién está allí?'. O un cliente simple: 'Ping', el servidor responde que 'Pong' funcionará bien.

Antecedentes

He trabajado con tomas en el pasado, pero sólo en Visual Basic 6 con el WINSOCKET.dll que era muy fácil para crear un servidor TCP/IP.

server.host = localhost; 
server.port = 12203; 
server.listen(); 

Con el cliente, solo tenía que hacer lo siguiente para conectarme.

client.connect(localhost, 12203); 

hubo algunas devoluciones de llamada disponibles, como la conexión, cierre, DataArrival, etc., que podría utilizar para hacer lo que quiera.

Tal vez para el iPhone hay bibliotecas escritas por ella, pero ¿es tan difícil de crear esta sencilla aplicación a sí mismo? Después de hacer algunas investigaciones, entiendo que tengo que buscar en el área de CFNetwork, CFHost, CFSocket, CFStream.

Pregunta

¿Hay alguien que me pueda guiar a un tutorial o publicar el código en el que tiene dos botones en el iPhone. [Start Server] y [Conectar al servidor] donde la primera se iniciará un servidor TCP/IP en un determinado puerto y la segunda se conecta a él.

Después de que se haya realizado una conexión, tal vez también el código para enviar un simple mensaje de 'Ping' al servidor después de que el servidor lo recibe, responde con un mensaje 'Pong' al cliente.

Eso sería realmente útil. Pero quizás estoy pidiendo mucho aquí.

+0

no está pidiendo demasiado SI al menos comenta CADA respuesta. votar por una solución también sería muy agradable. ;) –

Respuesta

17

this tutorial para crear una aplicación de muestra de chat funciona muy bien y es bastante sencillo (cualquier novato de iphone, como yo, puede hacerlo funcionar, AUN EN MODO SIMULADOR se conecta al servidor de socket externo).

lo he adaptado para hablar de mi servidor de socket y funciona como un encanto. este es el código de prueba, por lo que no hay una preocupación real con los cabos sueltos. solo envía un mensaje (su ID de inicio de sesión) y recibe una respuesta, que se muestra en la consola.

// 
// ViewController.m 
// zdelSocketTest01a 
// 
// 

#import "ViewController.h" 



@implementation ViewController 
@synthesize inputNameField; 
@synthesize joinView; 

- (void)initNetworkCommunication { 

    uint portNo = 5555; 
    CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"227.3.4.56", portNo, &readStream, &writeStream); 
    inputStream = (__bridge NSInputStream *)readStream; 
    outputStream = (__bridge NSOutputStream *)writeStream; 

    [inputStream setDelegate:self]; 
    [outputStream setDelegate:self]; 

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
    [inputStream open]; 
    [outputStream open]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Release any cached data, images, etc that aren't in use. 
} 

#pragma mark - View lifecycle 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    [self initNetworkCommunication]; 
    messages = [[NSMutableArray alloc] init]; 
} 

- (void)viewDidUnload 
{ 
    [self setInputNameField:nil]; 
    [self setJoinView:nil]; 
    [self setJoinView:nil]; 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 
} 

- (IBAction)joinChat:(id)sender { 

    NSString *response = [NSString stringWithFormat:@"logon,%@", inputNameField.text]; 
    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]]; 
    [outputStream write:[data bytes] maxLength:[data length]]; 

} 
/* 
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 
NSLog(@"stream event %i", streamEvent); 
} 
*/ 

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { 
    typedef enum { 
     NSStreamEventNone = 0, 
     NSStreamEventOpenCompleted = 1 << 0, 
     NSStreamEventHasBytesAvailable = 1 << 1, 
     NSStreamEventHasSpaceAvailable = 1 << 2, 
     NSStreamEventErrorOccurred = 1 << 3, 
     NSStreamEventEndEncountered = 1 << 4 
    }; 
    uint8_t buffer[1024]; 
    int len; 

    switch (streamEvent) { 

     case NSStreamEventOpenCompleted: 
      NSLog(@"Stream opened now"); 
      break; 
     case NSStreamEventHasBytesAvailable: 
      NSLog(@"has bytes"); 
      if (theStream == inputStream) { 
       while ([inputStream hasBytesAvailable]) { 
        len = [inputStream read:buffer maxLength:sizeof(buffer)]; 
        if (len > 0) { 

         NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; 

         if (nil != output) { 
          NSLog(@"server said: %@", output); 
         } 
        } 
       } 
      } else { 
       NSLog(@"it is NOT theStream == inputStream"); 
      } 
      break; 
     case NSStreamEventHasSpaceAvailable: 
      NSLog(@"Stream has space available now"); 
      break; 


     case NSStreamEventErrorOccurred: 
      NSLog(@"Can not connect to the host!"); 
      break; 


     case NSStreamEventEndEncountered: 

      [theStream close]; 
      [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

      break; 

     default: 
      NSLog(@"Unknown event %i", streamEvent); 
    } 

} 
/* 
- (void) messageReceived:(NSString *)message { 

[messages addObject:message]; 
[self.tView reloadData]; 

} 
*/ 

@end 

su archivo ViewController.h contendría

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController <NSStreamDelegate> 
@property (weak, nonatomic) IBOutlet UITextField *inputNameField; 
@property (weak, nonatomic) IBOutlet UIView *joinView; 
- (IBAction)joinChat:(id)sender; 


@end 
NSInputStream *inputStream; 
NSOutputStream *outputStream; 
NSMutableArray * messages; 

NOOBS solamente: usted debe vincular su botón y campo de texto pulsando CONTROL y arrastrando el objeto en la ventana de código. cuando lo haga, las propiedades anteriores se crearán automáticamente. marque this video tutorial si está perplejo

NOOBS SOLAMENTE 2: este conector saldrá en el PANEL DE CONSOLA de XCODE. en la esquina superior derecha de su ventana de xcode, haga clic en OCULTAR O MOSTRAR EL ÁREA DE DEPURACIÓN (solicite ayuda si es necesario).

construido y probado (simulador y dispositivo) en un macbook con memoria de 2GB, usando xcode 4.2 para el leopardo de las nieves.

+2

muchas gracias. Útil para mí. – piggy

+1

¿podemos tener el código fuente para la copia de trabajo? –

+0

@FahimParkar este es el código fuente de la versión de trabajo. si encuentra esto útil, espero que recuerde votar por UP, si es posible. tks. ;) –

1

Esperaría que quisiera que su servidor ya se haya iniciado, y luego solo necesitaría un botón "Conectarse al servidor", y luego su "Ping". De lo contrario, necesita un proceso separado en su cuadro de servidor que responde al mensaje "Iniciar servidor" e inicia el servidor.

+0

Oh, ¿así es como funciona? Para poder detectar un servidor como cliente, envía un mensaje a un determinado rango de ip local (por ejemplo, 192.168.1.1 -> 255) y a cada servidor que responda a ese mensaje que coloque en su TableView. De acuerdo, lo conseguiré. – Mark

+0

¿Hay alguna manera de ayudarme con la segunda parte de mi pregunta? ¿Cómo obtener el ping entre los dos? – Mark

+2

puerto de difusión de google. –

3

recomiendo lo siguiente: Cocoa Async Socket

También hay un proyecto básico ejemplo en el sitio para empezar. He tenido mucho éxito trabajando con ese marco.