SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

iPhoneネットワークプログラミング

TCP/IPを使用してサーバと通信する方法

  • このエントリーをはてなブックマークに追加

 外の世界と通信する方法を会得すると、非常に面白いアプリを作ることができます。本稿では、iPhoneプログラミングにおいて、TCP/IPによって他のサーバーと通信する方法や、簡単なチャットアプリの作り方を学びます。

  • このエントリーをはてなブックマークに追加

はじめに

 iPhoneプログラミングに関する筆者の前回の記事では、iPhoneアプリケーション内からWebサービスを利用(consume)し、そこから返されるXMLデータを解析する方法について考察しました。Webサービスは今とても流行っているものの、Webサービスを利用するために必要とされるペイロードはかなり大きく、わずかなデータを取り出したいだけの場合は無駄が多いように感じられます。問題は、SOAPパケット自体が多くのバイト数を消費することです。そこで、これに代わる方法としてソケットを利用することを考えます。ソケットを使えば、余分なXMLペイロードなしに情報をやり取りすることが可能です。また、サーバとの接続が確立した状態を維持できるので、アプリケーションを非同期で動かして、送られてきたデータを必要なときだけ受け取るようなことも可能です。

 本稿では、TCP/IPを使用してサーバと通信する方法を学びます。また、筆者が以前書いた記事の中で述べたアイデアを使って、簡単なチャットアプリを作ります。

 本稿のサンプルプロジェクトでは、Xcodeを使用し、新規のView-based ApplicationプロジェクトをNetworkという名前で作成します。

ストリームによるネットワーク通信

 ネットワーク上でソケットを使用して通信するときはNSStreamクラスを使うのが簡単です。NSStreamはストリームを表す抽象クラスで、これを使ってデータを読み書きできます。このクラスはメモリ、ファイル、ネットワークに対して有効です。NSStreamクラスを使うと、NSStreamオブジェクトに対してデータを読み書きするだけでサーバと通信できます。

 Mac OS Xでサーバとの接続を確立するには、NSHostオブジェクトとNSStreamオブジェクトを次のように使います。

NSInputStream *iStream;
NSOutputStream *oStream;
uint portNo = 500;

NSURL *website = [NSURL URLWithString:urlStr];
NSHost *host = [NSHost hostWithName:[website host]];
[NSStream getStreamsToHost:host 
                      port:portNo 
               inputStream:&iStream
              outputStream:&oStream];

 ご存じのように、NSStreamクラスにはgetStreamsToHost:port:inputStream:outputStream:というクラスメソッドがあり、これでサーバに対して入力ストリームと出力ストリームを作成してデータを読み書きできます。しかし、問題はgetStreamsToHost:port:inputStream:outputStream:メソッドがiPhone OSでサポートされていないことです。そのため、上記のコードはiPhoneアプリでは動きません。

 この問題は、既存のNSStreamクラスにカテゴリを追加してgetStreamsToHost:port:inputStream:outputStream:メソッドによる機能を置き換えれば解決できます。具体的には、Xcode内でClassesグループを右クリックし、新規のファイルをNSStreamAdditions.mという名前で追加し、NSStreamAdditions.hファイルに次のコードを追加します。

#import 

@interface NSStream (MyAdditions)

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

@end

 また、NSStreamAdditions.mファイルに、リスト1のコードを追加します。

 上のコードにより、getStreamsToHostNamed:port:inputStream:outputStream:というクラスメソッドがNSStreamクラスに追加され、iPhoneアプリからこのメソッドを使ってサーバとのTCP接続を行えるようになります。

※筆者注

 ここに示したカテゴリのコードは、AppleのTechnical Q&A1652を手本にしています。

リスト1
#import "NSStreamAdditions.h"

@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) && (port < 65536) );
    assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );
    
    readStream = NULL;
    writeStream = NULL;
    
    CFStreamCreatePairWithSocketToHost(
                                       NULL, 
                                       (CFStringRef) hostName, 
                                       port, 
                                       ((inputStreamPtr  != nil) ? &readStream : NULL),
                                       ((outputStreamPtr != nil) ? &writeStream : NULL)
                                       );
    
    if (inputStreamPtr != NULL) {
        *inputStreamPtr  = [NSMakeCollectable(readStream) autorelease];
    }
    if (outputStreamPtr != NULL) {
        *outputStreamPtr = [NSMakeCollectable(writeStream) autorelease];
    }
}

@end

 NetworkViewController.mファイルに、以下のステートメントを挿入します。

#import "NetworkViewController.h"

#import "NSStreamAdditions.h"

@implementation NetworkViewController

NSMutableData *data;

NSInputStream *iStream;
NSOutputStream *oStream;

 connectToServerUsingStream:portNo:メソッドを定義します。これでサーバに接続して、入力ストリームと出力ストリームのオブジェクトを作成できます。

-(void) connectToServerUsingStream:(NSString *)urlStr 
                            portNo: (uint) portNo {

    if (![urlStr isEqualToString:@""]) {
        NSURL *website = [NSURL URLWithString:urlStr];
        if (!website) {
            NSLog(@"%@ is not a valid URL");
            return;
        } else {
            [NSStream getStreamsToHostNamed:urlStr 
                                       port:portNo 
                                inputStream:&iStream
                               outputStream:&oStream];            
            [iStream retain];
            [oStream retain];
            
            [iStream setDelegate:self];
            [oStream setDelegate:self];
            
            [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                               forMode:NSDefaultRunLoopMode];
            [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
                               forMode:NSDefaultRunLoopMode];
            
            [oStream open];
            [iStream open];            
        }
}    

}

 入力ストリームと出力ストリームの両方が、実行ループ上でイベントを受け取るようにスケジュールしてあります。これで、ストリームにデータがなくなってもコードが中断されなくなります。また、両方のストリームオブジェクトのデリゲート(delegate)をselfに設定しているのは、ストリーム上のデータを受け取るメソッドをこの同じクラスに実装するからです。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
CFNetworkによるネットワーク通信

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Wei-Meng Lee(Wei-Meng Lee)

Microsoft MVP受賞者。Microsoft社の最新テクノロジー実地研修を専門とするDeveloper Learning Solutions社を創設。.NETとワイヤレステクノロジーの開発者、指導者として知られる。国際的なカンファレンスでたびたび講演し、.NET、XML、ワイヤレステクノロジーに関す...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4936 2010/04/19 19:08

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング