У меня есть этот пример кода, взятый из примера этого iPhone chat server.iphone socket stream buffer различен на симуляторе и iPhone 6 плюс?
В моем случае мне нужно отправить большие объемы данных, 100k-200k, таким образом, я изменил размер буфера на то, что может вместить то, что я хочу.
На симуляторе iOS (эмуляция 6plus) все работает отлично, как только я пытаюсь отлаживать свой iPhone 6plus после реализации предложений @tc. Я получаю входящее сообщение, разбитое на 3-4 части! Есть идеи?
2015-02-03 22:42:34.756 Sock1[7390:3773054] Incoming message: XML part 1
2015-02-03 22:42:34.759 Sock1[7390:3773054] Incoming message: XML part 2
2015-02-03 22:42:34.774 Sock1[7390:3773054] Incoming message: XML part 3
2015-02-03 22:42:34.794 Sock1[7390:3773054] Incoming message: XML part 4
XML-часть 1-4 составляет все сообщение, которое должно быть в одном, поскольку в нем нет символа нулевого байта.
Просто, чтобы сделать вещи еще более странные, когда я добавить точку останова на этой линии:
[currentMessage appendBytes:buffer length:len];
и пройти шаг за шагом (69-70 нажав Продолжить) все работает отлично! Никаких ошибок! Так что это связано со скоростью разбора или получения или чего-то, что я не могу понять?
Я уверен, что сервер не отправляет нулевые байт-символы, кроме конечного в конце сообщения.
код я использую это:
@implementation ViewController
bool connectionError = true;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)@"192.168.1.1", 6035, &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)closeAll {
NSLog(@"Closing streams.");
[inputStream close];
[outputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream setDelegate:nil];
[outputStream setDelegate:nil];
inputStream = nil;
outputStream = nil;
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(@"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
connectionError = false;
if (theStream == inputStream) {
uint8_t buffer[1024];
long len;
NSMutableData *currentMessage;
currentMessage = [NSMutableData dataWithBytes:"" length:strlen("")];
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
[currentMessage appendBytes:buffer length:len];
}
NSString *newMessage = [[NSString alloc] initWithData:currentMessage encoding:NSUTF8StringEncoding];
NSLog(@"Incoming message: %@",newMessage);
NSData *nullByte = [NSMutableData dataWithLength:1];
len = currentMessage.length;
NSRange searchRange = {0, len};
for (NSRange r; (r = [currentMessage rangeOfData:nullByte options:0 range:searchRange]).length;) {
NSString *message = [[NSString alloc] initWithBytes:currentMessage.bytes length:r.location encoding:NSUTF8StringEncoding];
searchRange.location = r.location+r.length;
searchRange.length = len - searchRange.location;
[self messageReceived:message];
}
[currentMessage replaceBytesInRange:(NSRange){0, searchRange.location} withBytes:NULL length:0];
}
break;
case NSStreamEventErrorOccurred:
NSLog(@"Can not connect to the host!");
connectionError = true;
[self closeAll];
[self connectionLost];
break;
case NSStreamEventEndEncountered:
break;
default:
NSLog(@"Unknown event");
}
}
- (void) connectionLost {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert!"
message:@"Connection to the server lost!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
- (void) messageReceived:(NSString *)message {
[messages addObject:message];
if (inputStream.streamStatus == NSStreamStatusClosed || inputStream.streamStatus == NSStreamStatusError || inputStream.streamStatus == NSStreamStatusNotOpen) {
[self closeAll];
[self initNetworkCommunication];
}
// do things with the message, XML parsing...
}
- (void) initConnection {
[self initNetworkCommunication];
messages = [[NSMutableArray alloc] init];
}
- (IBAction)joinChat:(id)sender {
[self initConnection];
[self sendSocketMessage: @"iam:" message: _inputNameField.text];
}
- (void) sendSocketMessage:(NSString*) sendCommand message:(NSString*) sendMessage
{
// do something...
if (outputStream.streamStatus == NSStreamStatusClosed || outputStream.streamStatus == NSStreamStatusError || outputStream.streamStatus == NSStreamStatusNotOpen) {
[self closeAll];
[self initNetworkCommunication];
}
NSString *response = [NSString stringWithFormat: @"%@%@", sendCommand, sendMessage];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
NSLog(@"clint sent: %@", response);
}
@end
Спасибо за ваш вход @tc. ! Я работаю над личным проектом только для iOS8, и ваш код очень помог! Теперь, чтобы узнать, как я могу восстановиться, когда соединение сломается ... но это еще одна тема (http://stackoverflow.com/questions/28265700/recovering-a-lost-connection-using-sockets) ... – Kostas
I говорил слишком быстро @ tc.Я отредактировал вопрос по мере возникновения другого типа проблемы ... – Kostas
'currentMessage' должен быть ivar, а не локальной переменной. –