Сокет-сервер iPhone / IP / клиентская программа - PullRequest
23 голосов
/ 17 сентября 2009

Я прочитал много вопросов по этому вопросу на этом сайте, но они не ответили на мой вопрос. Если вы не можете быть ### о моей цели или истории вопроса, переходите к вопросу.

Моя цель

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

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

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

Фон

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

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

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

client.connect(localhost, 12203);

Было доступно несколько обратных вызовов, таких как connect, close, dataArrival и т. Д., Которые я мог использовать для выполнения всего, что я хочу.

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

Вопрос

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

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

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

Ответы [ 3 ]

18 голосов
/ 23 апреля 2013

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

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

//
//  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 и перетащив объект в окно кода. когда вы сделаете это, свойства выше будут созданы автоматически. отметьте этот видеоурок если вы в тупике

ТОЛЬКО NOOBS 2: этот сокет будет выводиться в КОНСОЛЬНОЙ ПАНЕЛИ XCODE. в правом верхнем углу окна xcode нажмите HIDE OR SHOW THE DEBUG AREA (обратитесь за помощью, если необходимо).

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

3 голосов
/ 16 мая 2011

Я рекомендую следующее: Асинхронное гнездо какао

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

1 голос
/ 28 сентября 2009

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

...