2009-09-17 5 views
20

Я прочитал много вопросов по этому вопросу на этом веб-сайте, однако они не помогли ответить на мой вопрос. Если вы не можете указать ### о моей цели или фону, перейдите к вопросу.iPhone TCP/IP Socket Server/Client Program

Моя цель

ли построить сервер, который может работать на Mac OS X 10.4 и более поздних версиях порт его Windows XP/Vista (не знаю, как сделать это еще, но это проблема Для последующего).

Затем пусть iPhone будет клиентом, который сможет видеть имена компьютеров, на которых работает сервер (через WiFi). Затем пользователь iPhone может выбрать имя компьютера для подключения к серверу на этом компьютере.

После этого они могут отправлять простые текстовые сообщения друг другу. Например, iPhone отправляет «Knock Knock», и сервер отвечает «Кто там?». Или простой клиент: «Ping», сервер отвечает «Понг» будет прекрасно.

фон

Я работал с сокетами в прошлом, но только в Visual Basic 6 с WINSOCKET.dll это было очень легко создать TCP/IP сервера.

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

С клиентом мне нужно было только сделать следующее для подключения.

client.connect(localhost, 12203); 

Были некоторые функции обратного вызова доступны, как подключить, близкие, DataArrival и т.д., которые я мог бы использовать, чтобы сделать все, что хочу.

Возможно, для iPhone есть библиотеки, написанные для него, но трудно ли создать это простое приложение самостоятельно? После некоторых исследований я понимаю, что мне приходится смотреть в области CFNetwork, CFHost, CFSocket, CFStream.

Вопрос

Есть ли кто-нибудь, что может направить меня на учебник или опубликовать код, в котором у вас есть две кнопки на iPhone. [Запустить сервер] и [Подключиться к серверу], где первый запустит сервер TCP/IP на определенном порту, а второй подключится к нему.

После того, как было произведено соединение, возможно, также код для отправки простого сообщения «Ping» на сервер после получения сервером ответа с клиентом «Понг».

Это было бы действительно полезно. Но, может быть, я прошу многое здесь.

+0

Вы не просите слишком много, если вы хотя бы прокомментируете КАЖДЫЙ ответ. голосование за решение было бы очень приятно. ;) –

ответ

17

this tutorial для создания примера приложения для чата работает очень хорошо и довольно просто (любой iphone noob, как и я, может заставить его работать, ДАЖЕ В РЕЖИМЕ SIMULATOR он подключается к внешнему серверу сокетов).

Я адаптировал его, чтобы говорить на моем сервере сокетов, и это работает как шарм. это тестовый код, поэтому нет никакой реальной проблемы со свободными концами. он отправляет только одно сообщение (ваш идентификатор входа в систему) и получает ответ, который он показывает в консоли.

// 
// 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 

файл ViewController.h будет содержать

#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 ТОЛЬКО: вы должны связать кнопку и текстовое поле, нажав CONTROL и перетащить объект в окно кода. когда вы это сделаете, свойства, указанные выше, будут автоматически созданы. проверьте this video tutorial, если вы заблокированы

NOOBS ТОЛЬКО 2: этот разъем будет выводиться в CONSOLE PANE XCODE. в правом верхнем углу окна вашего xcode нажмите «СКРЫТЬ» ИЛИ ПОКАЗАТЬ ОБЛАСТЬ ДЕБЮГА (при необходимости обратитесь за помощью).

встроенный и протестированный (симулятор и устройство) на macbook с памятью 2 ГБ, используя xcode 4.2 для снежного барса.

+2

большое спасибо. Полезно для меня. – piggy

+1

У нас есть исходный код для рабочей копии? –

+0

@FahimParkar это исходный код для рабочей версии. если вы найдете это полезным, я надеюсь, что вы помните, чтобы проголосовать, если это возможно. ТКС. ;) –

1

Я ожидаю, что вы захотите, чтобы ваш сервер уже был запущен, а затем вам понадобится только кнопка «Подключиться к серверу», а затем ваш «Ping». В противном случае вам потребуется отдельный процесс на вашем сервере, который отвечает на сообщение «Начать сервер» и запускает сервер.

+0

О, так вот как это работает? Чтобы иметь возможность обнаруживать сервер в качестве клиента, вы отправляете сообщение в определенный локальный диапазон IP (например, 192.168.1.1 -> 255) и каждый сервер, ответивший на это сообщение, которое вы помещаете в свой TableView. Хорошо, я это получу. – Mark

+0

Есть ли способ помочь мне со второй частью моего вопроса? Как получить пинг между двумя? – Mark

+2

порт передачи Google. –

3

Я рекомендую следующее: Cocoa Async Socket

Там также базовый пример проекта на сайте, чтобы вы начали. У меня был хороший успех, работая с этой структурой.