#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;
}