1

ソケット接続のもう一方の端に関係なく、ストリームが別のスレッドによって閉じられた場合、NSInputStreamオブジェクトはread:メソッドからポップアウトする必要があるように思われます。しかし、場合によっては、これは真実ではないように見えます。相手側が接続の前に少なくとも1回何かを最初に送信しない限り、read:メソッドはストリームの終了に応答しないようです。

接続を開くためのコード:

    // Open the socket...
    CFStreamCreatePairWithSocketToHost(NULL, Host, Port, &readStream, &writeStream);

    // Create NSStream objects for our use...
    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;

    // take ownership of the NSStream objects...
    [inputStream retain];
    [outputStream retain];

    // open the streams....
    [inputStream open];
    [outputStream open];

接続を閉じるためのコード:

    // Close the streams...
    [inputStream close];
    [outputStream close];

    // Release ownership...
    [outputStream release];
    [inputStream release];

    // clear reference values...
    outputStream = nil;
    inputStream = nil;

受信スレッド:

-(uint8_t) GetByte
{
    uint8_t c;
    int N = [inputStream read:&c maxLength:1];
    if ( N < 1 )
        @throw [[TcpClientException alloc] init];
    return c;
}

メインスレッドからストリームを閉じようとすると、受信スレッドはreadメソッドのままになります。最終的にはタイムアウトしてクラッシュします。クラッシュしても、どのような種類のオブジェクトもスローされません(コードを囲んで何か(id)をキャッチしようとしましたが、何も得られませんでした)。

ストリームが閉じられるたびに、どのようにして読み取りを確実に強制的にポップアウトさせるのでしょうか。

さらに:

私は5.1iPadシミュレーターを備えたMLでXCODE4.4.1を使用しています。

inputStreamを閉じるだけで、リリースまたはnilに設定しない場合、問題も発生します。

4

1 に答える 1

0

多くの調査の後、私はここSOで、ローカルデバイスが切断されているため、readメソッドを通過する接続(リモートエンドポイントから)からのイベントが発生しないという答えを示唆する別のスレッドに出くわしました。アイデアは、ローカルデバイスが切断を担当しているため、readメソッドに入らないようにする(読み取るものがない)ことを認識しているというものでした。レシーバースレッドがすでにreadメソッドに含まれている場合、ユーザーが切断している可能性があるため、これは少し予想外のことです。しかし...iOSは、レシーバースレッドではなく、実行ループ内のイベントに依存するように設計されているようです(これは別の問題ですが、ここでは取り上げたくありません)。具体的には、使用可能なデータがあることを示す実行ループからのイベントが与えられた場合、readメソッドを入力します。したがって、読み取りを入力して最初のバイトを待ってハングすることはありません。これは、過去にWindowsプラットフォームで行ったソケットプログラミングとは大きく異なります。しかし、私がこれまでに行ったすべての実験は、これが問題であることを示しています。ネットワークトラフィックがGUI(メイン)スレッドに干渉しないように、ワーカースレッドの実行ループから発生するストリームからのイベントに依存するソリューションがあります。

于 2012-09-07T21:05:22.980 に答える