Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send NSString through socket using NSOutputStream

I have to create a chat app for iOS using socket programming and my IP address is 192.168.0.57:9300. I have used Raywenderlich socket programming example,receiving data working properly but sending not working ,there are no any error or crash. My code are as follows.

code for opening streams

- (void) initNetworkCommunication {

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.57", 9300, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];    
}

code for sending data

- (IBAction)sendMessage:(id)sender
{
        NSString *response  = @"lets start chat";
        NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
        [outputStream write:[data bytes] maxLength:[data length]]; 
}

Delegates

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {

    NSLog(@"stream event %i", streamEvent);

    switch (streamEvent) {

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;
        case NSStreamEventHasBytesAvailable:

            if (theStream == inputStream) {

                uint8_t buffer[1024];
                int len;

                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(@"\nreciving data------%@,buffer);

                            [self messageReceived:output];

                        }
                    }
                }
            }
            break;


        case NSStreamEventErrorOccurred:

            NSLog(@"Can not connect to the host!");
            break;

        case NSStreamEventEndEncountered:

            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [theStream release];
            theStream = nil;

            break;
        default:
            NSLog(@"Unknown event");
    }

}
Message sending
    - (void) messageReceived:(NSString *)message {

        [self.messages addObject:message];
        [self.tView reloadData];
        NSIndexPath *topIndexPath = [NSIndexPath indexPathForRow:messages.count-1 
                                                       inSection:0];
        [self.tView scrollToRowAtIndexPath:topIndexPath 
                          atScrollPosition:UITableViewScrollPositionMiddle 
                                  animated:YES];

    }

please provide me suggestion.

like image 223
Suraj Avatar asked Oct 10 '12 11:10

Suraj


3 Answers

You should add the "\n" at the end of your response like this:

- (IBAction)sendMessage:(id)sender
{
        NSString *response  = @"lets start chat\n";
        ////your code
}

This work for me, but my problem is that I cannot receive data using the function (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent

like image 85
Nguyen Thanh Hung Avatar answered Nov 15 '22 11:11

Nguyen Thanh Hung


I had similar problem. Got it solved by appending new-line and line-feed character in string.

- (IBAction)sendMessage:(id)sender {

        NSString *response  = @"lets start chat\r\n\r\n";
        NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
        [outputStream write:[data bytes] maxLength:[data length]]; 
}
like image 22
Jayprakash Dubey Avatar answered Nov 15 '22 12:11

Jayprakash Dubey


I found writing a separate thread solved this issue for me.
Makes sense as one shouldn't really do network ops on the main thread.
Here is my code:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^(void) {
    NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
    NSInteger len = [outputStream write:[data bytes] maxLength:[data length]];
    NSLog(@"Len = %ld", len);
});

Another point to note is that the NSStreamEventOpenCompleted event is called twice. Once when each of the input and output streams are opened. So one needs to be careful not to write to the output stream prior to its event.

like image 24
yerachw Avatar answered Nov 15 '22 11:11

yerachw