9

ソケット プログラミングを使用して iOS 用のチャット アプリを作成する必要があり、私の IP アドレスは192.168.0.57:9300. ソケット プログラミングの例を使用Raywenderlichしました。データは正しく受信されますが、送信は機能しません。エラーやクラッシュはありません。私のコードは次のとおりです。

ストリームを開くためのコード

- (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];    
}

データ送信用コード

- (IBAction)sendMessage:(id)sender
{
        NSString *response  = @"lets start chat";
        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);

    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];

    }

私に提案をしてください。

4

3 に答える 3

5

次のように、応答の最後に「\n」を追加する必要があります。

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

これは私にとってはうまくいきますが、関数を使用してデータを受信できないという問題があります(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent

于 2013-04-27T15:05:21.733 に答える
1

同様の問題がありました。文字列に改行と改行文字を追加することで解決しました。

- (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]]; 
}
于 2014-10-17T05:10:28.883 に答える
1

別のスレッドを書くと、この問題が解決することがわかりました。
メインスレッドでネットワーク操作を実際に行うべきではないため、理にかなっています。
これが私のコードです:

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

もう 1 つの注意点は、NSStreamEventOpenCompleted イベントが 2 回呼び出されることです。入力ストリームと出力ストリームのそれぞれが開かれたときに 1 回。そのため、イベントの前に出力ストリームに書き込まないように注意する必要があります。

于 2014-12-07T16:41:58.157 に答える