Простое подключение клиента Iphone к серверу

#iphone #objective-c #sockets #nsstring #nsstream

#iPhone #objective-c #сокеты #nsstring #nsstream

Вопрос:

Заранее спасибо тем, кто просматривает мой вопрос. я новичок в программировании, а также новичок в программировании на Objective-c, я создаю простой клиент, который будет подключаться к дневному серверу и запрашивать время и дату, а затем выводить его на экран, я смотрел и читал много руководств прямо сейчас и придумал приведенный ниже код, ноу меня проблема, я не могу прочитать ввод от пользователя, который введет адрес сервера, и я буду использовать этот адрес сервера для подключения к серверу вот мой код

мои коды сокетов в моем файле controller.m

 @interface NSStream (MyAdditions)

  (void)getStreamsToHostNamed:(NSString *)hostName 
                         port:(NSInteger)port 
                  inputStream:(NSInputStream **)inputStreamPtr 
                 outputStream:(NSOutputStream **)outputStreamPtr;

@end

@implementation NSStream (MyAdditions)              
  (void)getStreamsToHostNamed:(NSString *)hostName 
                         port:(NSInteger)port 
                  inputStream:(NSInputStream **)inputStreamPtr 
                 outputStream:(NSOutputStream **)outputStreamPtr
{
    CFReadStreamRef     readStream;
    CFWriteStreamRef    writeStream;

    assert(hostName != nil);
    assert( (port > 0) amp;amp; (port < 65536) );
    assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );

    readStream = NULL;
    writeStream = NULL;

    CFStreamCreatePairWithSocketToHost(
                                       NULL, 
                                       (CFStringRef) hostName, 
                                       port, 
                                       ((inputStreamPtr  != nil) ? amp;readStream : NULL),
                                       ((outputStreamPtr != nil) ? amp;writeStream : NULL)
                                       );

    if (inputStreamPtr != NULL) {
        *inputStreamPtr  = [NSMakeCollectable(readStream) autorelease];
    }
    if (outputStreamPtr != NULL) {
        *outputStreamPtr = [NSMakeCollectable(writeStream) autorelease];
    }
}

@end
  

Мой адрес и порт подключения

 @implementation iPhoneClientViewController

-(void) connect {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *address = [defaults stringForKey:@"Address"]; // this is default one 
    if(!address) address = @"localhost";
    NSLog(@"ADDRESS %@",address);

    [NSStream getStreamsToHostNamed: address port:13 inputStream:amp;iStream outputStream:amp;oStream];
    [iStream retain];
    [oStream retain];
    [iStream setDelegate:self];
    [oStream setDelegate:self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [iStream open];
    [oStream open];
}
  

мои значения по умолчанию

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
   <key>Title</key>
   <string>iPhoneClient</string>
   <key>StringsTable</key>
   <string>Root</string>
   <key>PreferenceSpecifiers</key>
   <array>
    <dict>
      <key>Type</key>
      <string>PSTextFieldSpecifier</string>
      <key>Title</key>
      <string>Server IP</string>
      <key>Key</key>
      <string>Address</string>
      <key>DefaultValue</key>
      <string>localhost</string>
      <key>IsSecure</key>
      <false/>
      <key>KeyboardType</key>
      <string>NumbersAndPunctuation</string>
      <key>AutoCorrectType</key>
      <string>No</string>
    </dict>
   </array>
  </dict>
</plist>
  

i put a text field to my ViewController.m

 -(BOOL)textFieldShouldReturn:(UITextField *)textField{
    NSLog(@"Text Field contents %@",textField.text);
    [textField resignFirstResponder];
    return YES;
}
  

and when button clicked i put

 - (IBAction)connectCommand:(id)sender {
    // NSString *address = textField.text; // this is gives me error textField  undeclared
    // then i try this one
    NSString *address = text.text;
    if( iStream != nil) return;
    [self connect];
}
  

then i run program i enter the address then i click to connect button but it doesnt work it gives me following errors on output screen

 2011-10-03 17:49:14.903 iPhoneClient[360:b303] Text Field contents 64.90.182.55 
2011-10-03 17:49:16.096 iPhoneClient[360:b303] ADDRESS localhost
2011-10-03 17:49:16.101 iPhoneClient[360:b303] >> : NSStreamEventErrorOccurred
2011-10-03 17:49:16.102 iPhoneClient[360:b303] << : NSStreamEventErrorOccurred
  

my event handling is like following

 - (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
    NSString *io;
    if (theStream == iStream) io = @">>";
    else io = @"<<";

    NSString *event;
    switch (streamEvent)
    {
        case NSStreamEventNone:
            event = @"NSStreamEventNone - Can not connect to the host!";
            break;
        case NSStreamEventOpenCompleted:
            event = @"NSStreamEventOpenCompleted";
            break;
        case NSStreamEventHasBytesAvailable:
            event = @"NSStreamEventHasBytesAvailable";
            if (theStream == iStream)
            {
                //read data
                uint8_t buffer[1024];
                int len;
                while ([iStream hasBytesAvailable])
                {
                    len = [iStream read:buffer maxLength:sizeof(buffer)];
                    if (len > 0)
                    {
                        NSString *input = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
                        if (nil != input)
                        {
                            //do something with data
                            NSLog(@"%@",input);
                        }
                    }
                }
            }
            break;
        case NSStreamEventHasSpaceAvailable:
            event = @"NSStreamEventHasSpaceAvailable";
            break;
        case NSStreamEventErrorOccurred:
            event = @"NSStreamEventErrorOccurred";
            break;
        case NSStreamEventEndEncountered:
            event = @"NSStreamEventEndEncountered";
            [self disconnect];
            break;
        default:
            event = @"** Unknown";
    }

    NSLog(@"%@ : %@", io, event);
}
  

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

=====================================================================================================

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

я думаю, что я пойду с низким уровнем, да, работа с xml немного усложняется, поэтому я просто отключил части

 //NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    //NSString *address = [defaults stringForKey:@"Address"];
    //if(!address) address = @"localhost";]
  

и поместите этот код

     NSString *address = [text text];
    NSLog(@"ADDRESS %@",address);
  

теперь на моем экране вывода я получаю следующее =

 2011-10-03 18:58:57.758 iPhoneClient[424:b303] Text Field contents 64.90.182.55 
2011-10-03 18:58:58.627 iPhoneClient[424:b303] ADDRESS 64.90.182.55 
2011-10-03 18:58:58.685 iPhoneClient[424:b303] >> : NSStreamEventOpenCompleted
2011-10-03 18:58:58.686 iPhoneClient[424:b303] << : NSStreamEventOpenCompleted
2011-10-03 18:58:58.686 iPhoneClient[424:b303] << : NSStreamEventHasSpaceAvailable
2011-10-03 18:58:58.696 iPhoneClient[424:b303] >> : NSStreamEventHasBytesAvailable
2011-10-03 18:58:58.698 iPhoneClient[424:b303] >> : NSStreamEventEndEncountered
  

я думаю, что он говорит, что он подключен, но поскольку я ничего не делаю с данными, он завершает работу, потому что я ввел цикл выполнения выше?

теперь кто-нибудь знает, как я могу получить и распечатать дату и время с сервера?

Ответ №1:

Высокий уровень обратной связи:

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

Вместо этого рассмотрите возможность использования JSON или XML в качестве более управляемого формата. Объединив это с RESTful API, вы можете использовать HTTP-запросы от iOS и взаимодействовать с вашим сервером более производительным, переносимым и управляемым способом.

Надеюсь, это поможет.

Комментарии:

1. спасибо за совет, но я должен изучить этот тип даже с сокетами BSD на C, тогда я могу использовать другие способы решения своих проблем, но я думаю, что решил свою первую проблему. я думаю, что теперь я могу подключиться к серверу с помощью строки из текстового поля, я отредактировал свой пост выше

Ответ №2:

в методах:

 NSString *address = [text text];
  

когда пользовательская вкладка возвращает клавишу на клавиатуре:

 -(BOOL)textFieldShouldReturn: (UITextField *)textField {
    NSLog(@"Text Field contents %@",textField.text);
    [textField resignFirstResponder];
    return YES;
}