ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Introducing Network.framework: A modern alternative to Sockets
The new Network.framework API gives you direct access to the same high-performance user-space networking stack used by URLSession. If you're considering using Berkeley Sockets in your app or library, learn what better options are available to you.
リソース
- Implementing netcat with Network Framework
- Supporting IPv6 DNS64/NAT64 Networks
- URLSession
- WWDC2013 - What's New in Foundation Networking
- WWDC2014 - What's New in Foundation Networking
- WWDC2015 - Networking with NSURLSession
- プレゼンテーションスライド(PDF)
関連ビデオ
WWDC21
WWDC20
-
ダウンロード
(音楽)
(拍手) おはようございます
ジョシュ・グレスリーです 今日はNetwork.frameworkを 紹介します
Network.frameworkは ソケットの代替です これから トランスポートAPIの 話をします Network.frameworkの システムへの組み込みと アプリケーションへの 適合性が分かると思います 最初の接続を通し このAPIを紹介します 実際にデータ通信を 最適化する方法と 驚異的なパフォーマンスを お見せしましょう このAPIがモビリティの課題を どう処理するのか また このAPIの採用方法を お話しします
まずトランスポートAPIについて 説明します ネットワーク上の エンドポイント間で 任意のデータを 送受信できるAPIを指します このカテゴリに該当する APIは多数あります
ソケットは普及率が高く 30年以上前からあります ソケットの登場で 世界は一変したと言えますが 今の時代のアプリケーションを ソケットで書くのは困難です ソケットの使用が難しい 領域は3つあります
1つ目は接続の確立 ソケットでの接続が 難しい理由は多くあります アドレスに接続すると 大抵はホスト名しかないため ホスト名を アドレスに解決します すると複数のアドレスが 出てくるのです IPv4アドレスや IPv6アドレスです どの順番で どのアドレスに接続するか? 次の接続のタイミングは? 答えを得るには 何年もかかるでしょう
デュアルスタックのホストの後は 他の問題に直面します プロキシ自動設定や PACもありますが これらにはJavaScriptがあり URLを渡す必要があります JavaScriptは 直接行くことができるのか または SOCKSプロキシや HTTPプロキシが必要か応答します アプリケーションがこれらを サポートする必要があれば 厄介かもしれません ネットワークのテストをせず 顧客から不具合の報告を受け 不満を言われる 可能性もあります 解決のためにコードを追加しても それをテストできません 顧客と同じ環境を 再現するのは本当に困難です 1つ目は接続でした
2つ目の難しい領域は データ転送です これが難しい理由は たくさんあります
主な問題はソケットの 読み書きのモデルです 並列処理のできない ブロッキングソケットは データの読み書きの間 単一の処理は避けるべきです 非ブロッキングにしても 別の課題に直面します カーネルに100バイトが 欲しいと言うと “また後で”と 返されるかもしれません そして ステートマシンの 構築が必要になります これは大変な作業で 非常に困難です
さらにTLSを 使用する必要があるため ソケットへの読み書きは 避けるべきです
ソケットはTLSを サポートしていません TLS対応の ライブラリを使用するか グルーコードを 書くことになります そして膨大な接続ロジックで 動作方法を探るのです
難しいですね
最後の問題はモビリティです 理由は多くあります
以前は1つのデバイスを 移動させるのに 2人以上が必要でした 1本のケーブルに静的IPアドレス 全てがシンプルでした 現代ははるかに パワフルなデバイスがあります 複数の電波を放ち ネットワーク間を移動するには アプリケーションが移行を うまく処理する必要があります
ソケットには無理です ルーティングソケットでも 難しいでしょう トランスポートAPIの出番です
プラットフォームには APIがURLセッションにあります これら全ての問題を 処理してくれます TCPとTLS接続へ 生でアクセス可能な― ストリームタスクもあります
URLセッションが 自分と同じプリミティブ上に 構築されていると 思うかもしれません
しかし 違います Network.frameworkの上に 構築されているのです HTTPに焦点を当て 多くのトランスポート機能を Network.frameworkに 降ろしました
Network.frameworkに 長年取り組む我々は 学んだ多くのことを IETFに反映しています IETFへ参加して 他の企業のエンジニアと出会い 多くのことを 話し合ってきました フィードバックを元に Network.frameworkを 改善したのです 今年 皆さんのアプリケーションで そのライブラリを利用できます (拍手) ソケットは全てにおいて 細かいコントロールが可能です そこは利点です ソケットより優れた機能を持った Network.frameworkですが “取っ手”は残し 調節可能にしました 取っ手を回すほど 複雑なコントロールができるのです 必要な力だけを得られるので 無駄な複雑さを避けられます
Network.frameworkは スマートな接続の確立が可能です デュアルスタックや IPv6のみのネットワーク PAC プロキシを処理できます 他では扱いにくい ネットワークの接続に役立ちます 最適化された データ転送パスは ソケットの全ての パフォーマンスを超えているのです
セキュリティ機能に対応し TLSとDTLSを標準でサポート 本当に使いやすいです モビリティも サポートしています また 接続に関する ネットワークの変更を通知します
iOS macOS tvOSで 利用できるため Objective-Cから 簡単に使用できるのです Swift APIも備えています
ではここで トミー・ポーリーの登場です どうも (拍手)
こんにちは ネットワークチーム所属の トミー・ポーリーです Network.frameworkを アプリケーションへ 採用する方法をお話しします 最初の接続の確立から 始めましょう ローカルデバイスから サーバやピアデバイスへ接続します
Network.frameworkに 適した接続とは? ユースケースは? ソケットをNetwork.frameworkに 替える利点は大きいです その恩恵を得られる 1つ目のシナリオを紹介します
まずはゲームの アプリケーションです 大抵はUDPを使い デバイス間で リアルタイムのデータを送信します 通常はレイテンシを最適化し ラグやデータの損失を抑えています Network.frameworkでは UDPを最適化して 送受信の時間を非常に 速くすることができます
2つ目はLive Streamingの アプリケーションです UDPとTCPを組み合わせることが よくありますが 重要なのはその場で データを生成することです 新しいビデオフレームや オーディオフレームがある場合に 多くのバッファリングがあると うまくいきません 読み書きの非同期のモデルは バッファリングを減らすのに 最適でしょう
最後はメールとメッセージングの アプリケーションです TLSという昔ながらの プロトコルを使っていますが ネットワークの移行こそが とても重要なのです
メッセージングの アプリケーションは 多くの場合は 建物から出る時に使用します 建物のWi-Fiネットワークから モバイルデータ通信に移行した時に メッセージを 早く届けたいでしょう
これらは低レベルのネットワークを 利用する場合の例であり 他のケースでも利用できます 他のアプリケーションや ユースケースで どんな恩恵を 得られるか説明します メールやメッセージング アプリケーションの 接続の方法を見ましょう
メールの接続を例にとり セキュリティ機能を付けて TLSを組み合わせたIMAPを使います ホスト名は mail.example.comから始めます 993番ポートに接続し TLSとTCPを使います
通常のソケットなら― こう始まるでしょう ホスト名を取得し DNS APIを 呼び出し ホスト名を解決 例えばgetaddrinfoだとします 1つ以上のアドレスから どれに接続するか決めます 最適なアドレスファミリで ソケットを呼び オプションを設定 ソケットを 非ブロッキングにする場合は―
TCPを開始し 書き込み可能なイベントを待ちます 以上はTLSを使う前で 多くの手間がかかります
Network.frameworkの 場合は? もっとシンプルな使い方が できるといいですね まずは接続オブジェクトの 生成です 2つのことに基づいています 1つ目は宛先を定義する エンドポイント これは以前のIPアドレス かもしれませんが 通常はホスト名と ポートがあります エンドポイントは この2つです Bonjourサービスへの 接続かもしれません
2つ目はパラメータです TLS DTLS UDP TCPなど どのプロトコルを使うか定義します プロトコルのオプションと 接続をWi-Fiだけにするかなど 接続に使用するパスを定義します
設定が終われば startを呼び出し処理を開始 readyになるのを待ちます TLS接続に必要なのは これだけです Swiftではどうでしょう?
ネットワークモジュールを インポートし― NWConnectionオブジェクトを 生成します これはSwiftでも Objective-Cでも データの読み書きに 必要なオブジェクトです エンドポイントをホストで 初期設定できるため ホスト名をmail.example.comにし ポートを指定します ポートは よく知られているimapsです Swiftに簡単に入力でき 他の数値リテラルも入ります
使用するプロトコルを定義するため パラメータを渡します クライアント接続なので 標準のTLSとTCPのみです 単純に.tlsと書くだけで TLS接続ができました
次に stateUpdateHandlerで 接続の移行を処理します ready状態の処理が 特に重要です readyはデータの読み書きが できる状態を指します TCPとTLSの場合は ハンドシェイクの完了も意味します
waiting状態の 説明をしましょう 昨年 waitsForConnectivityを 紹介しましたが NWConnectionのwaiting状態は それと同じものです 標準でオンになっています 接続を生成し始め ネットワークがない場合は 利用可能になるまで 待ってくれます reasonコードも使えますが ネットワークが移行するまで 待つだけです モビリティはこのAPIに 必要不可欠です
エラーも通知します TLSの失敗などは失敗した イベントとして通知されます
セットアップ後 startを呼び出し コールバックを受け取るための ディスパッチキューを指定します
startを呼び出した時の 説明をしましょう これは簡単なステートマシン NWConnectionの内部です セットアップの状態から startを呼び出すと 準備の状態に移ります
準備の状態は― ただ接続を 呼び出す以上のことをします TCPソケットはサーバに SYNパケットを送るだけです
NWConnectionでstartを呼び出すと 多くの処理をします そして ネットワークを評価し 最速で接続するのです さらに掘り下げましょう Smart Connection Establishmentです
startを呼び出す時は まずエンドポイントを取得し 利用可能な ネットワークを評価します この場合はWi-Fiと モバイルデータ通信です コストが低く 人気の高いWi-Fiから 見ていきましょう
このネットワークの設定を 確認します VPNやプロキシの 有無を調べるのです 今回は自動設定ファイルで 設定されたプロキシがあり 接続が適合しない場合は 直接アクセスできるとします 2つのオプションを 評価します プロキシが必要なら接続し TCP接続を確立します 不要なら皆さんの代わりに DNSに問い合わせます 全てのIPアドレスの 応答を得て 1つずつ並行して 接続を試します 競争させることで 最速で接続します
Wi-Fiを使っていて 建物から離れて 電波が弱くなった場合は?
Wi-Fi アシストが 活用できます モバイルデータ通信に フォールバックし DNSで解決して 1つずつ接続を試します これにより接続を回復させ VPNやプロキシを処理し 最適な接続を 提供できるのです
オプションが 不要な方もいるでしょう 接続の確立を 制限したい場合は 取っ手や コントロールがあります 3つだけ紹介します
高価なネットワークを 使用したくない場合で Wi-Fiのみの使用が 適切だとします 接続のパラメータの中には インターフェイスを管理する オプションがあります モバイルデータ通信が 不要なら prohibitedInterfaceTypesに .cellularを追加します
高価なネットワークの禁止は 良いことです これは例えばMacの インターネット共有を防ぎます
接続の確立を制限する 他の方法は IPアドレスファミリの 選択の特定です とても速いIPv6を気に入っていて IPv4は使わないとします その場合はパラメータの IP固有のオプションが使えます ここには なじみ深い ソケットのオプションがあり IPのバージョンを 定義できます これが接続と DNSの解決に影響します
最後はプロキシが 不要な場合です SOCKSプロキシを通る接続が 不適切な時は プロキシの使用を 禁止できます
これが準備の状態です 設定時にネットワークが ない場合もあるでしょう DNSエラー 良いオプションや ネットワークがない場合 機内モードの時は waiting状態に移ります ネットワークの状態が変わり 接続できる状態になると 再試行を繰り返します 再試行の度に ユーザに通知が届きます
最終的に接続が確立されると ready状態へ移ります
これは接続が完全に 確立した状態です 以上がTLSに至るまでの 全てのプロトコルです 読み書きが可能です ここでネットワーク移行の コールバックを受け取ります ネットワークを変更する場合に 円滑に移行する方法があります 後ほどお話ししましょう
接続に何かエラーが 生じた場合は 確立失敗の状態であるという 通知がきます 接続を終了したり 無効にして 完全に断ちたい場合には キャンセルを呼び出せば 中止の状態に移ります 関連するメモリを クリーンアップするための オブジェクトを得て終了です
以上が接続オブジェクトの 基本的な流れです ではここでエリックを ステージに迎えます (拍手)
どうも エリック・キニアです 今からアプリケーションの 一例を構築します Live Streamingを例に 使いましょう あるデバイスから ネットワークを通して 別のデバイスに 映像を映し出します 継続的にビデオフレームを 生成するため UDPでパケットを ネットワークに送ります その方法は?
カメラでセッションを保存し イメージセンサーから ビデオフレームを受け取ります ビデオコーデックや 他の圧縮機能は使いません 低バイトのデータを受け取り 別の画面に映し出します
フレームを小さな塊に分割し UDPパケットを送信
当然 接続が必要になります
接続を受け取り データパケットを読み取る リスナーが必要です そして逆の手順で ビデオフレームを再構築し ディスプレイへ送ります
カメラとディスプレイ機能を 省くことで Network.frameworkを 使う部分に焦点を当てます
隠していない部分は リスナーです
リスナー機能は NWListnerで提供されており 接続の設定と同じ Parameterオブジェクトで作れます
Bonjourサービスを アドバタイズするリスナーの設定に 今回はcamera.udpを使用します
新しい接続を受け取ると newConnectionHandlerとして 提供したブロックへ渡します 接続中に選択した設定を実行し 開始を知らせるため startを呼び出します
同様にリスナーも startを呼び出し ディスパッチキューを 指定します
これがリスナーです UDPソケット上にリッスンを 呼び出すのと同等の機能です ただし リッスンは UDPソケットでは使えません
XcodeでAppを構築しましょう こちらにAppがあり カメラとディスプレイ機能を 操作するファイルがあります UDPClientクラスと UDPServerクラスに注目しましょう UDPClientはフレームを送る 接続を作成します サーバはそれらを受け取り データを読み取り画面に送る リスナーを作成します クライアントから始めます
イニシャライザが ネームを取り込みます ネームとはBonjour名を表す 文字列です
NWConnectionを呼び出し エンドポイントを通過させて 接続を作成します 名前と種類は camera.udpを使います
UDPパラメータも 通過しました
ready状態か 確立失敗の状態か―
ハンドラを使って 確認できます sendInitialFrameを呼び出し 1分以内に実行 他のハンドシェイクは ありません そのためビデオフレームを ネットワークに落とす前に 別のデバイスに送信し エコーバックを待ちます
そして自分の接続上で startを呼び出してください
最初のフレーム送信です
ここは“hello”というリテラルで データオブジェクトを作成 connection.sendを呼び出し データオブジェクトを コンテンツとして提供します 提供される完了ハンドラで 送信中のエラーを確認できます
エコーバックが欲しいので データを読み込むための connection.receiveを呼び出します その完了ハンドラの中で コンテンツを確認後 残りのアプリケーションに 接続されます そしてカメラハードウェアから フレームの生成を開始
この時 残りのアプリケーションが 送信を呼び出します
そしてそこに データオブジェクトを渡します
送信の操作を 早く完了させるため connection.batchを通った ブロック内だけで実行しましょう
このブロック内で 全てのフレームを調べ connection.sendへ渡します 先ほどと同様に 完了ハンドラでエラーを確認 これでUDPクライアントクラスが 完成しました
サーバを見てみましょう サーバ側には接続を受け取る リスナーが必要です 先ほどの ハンドシェイクに応答し データを読み取り ディスプレイに到達させましょう リスナーから始めます
まず UDPパラメータで NWリスナーを作成します
この時 ローカルポートを リッスンするよう リスナーに 伝えることもできます 今回はBonjourサービスのため 不要です
次にサービスプロパティを camera.udpタイプの サービスオブジェクトに 設定します デバイスネームを得るので ネームの受け渡しはしません
さらにserviceRegistration UpdateHandlerにブロックを提供し エンドポイントをいつでも 呼び出すことができます エンドポイントが 加えられる場所は? サーバ型なら 残りのアプリケーションに 初期設定の デバイスネームを伝えます それをユーザに 別の場所で入力させるのです
次は接続ハンドラの設定です これは接続を受け取る度に 呼び出されます
そしてconnection.startを呼び出し キューに送りましょう
ここで残りのアプリケーションに 接続を伝えると ビデオフレームを 表示する準備が整います そしてreceiveを呼び出し すぐに実行して データを読み取り パイプラインに送り出します
ここでも更新ハンドラで―
ready状態か確立失敗か 確認します
そしてlistner.startを呼び出し キューに送ります
次に ネットワークの情報を 読み取り 受信機能を実行
そしてconnection.receiveから 完了ハンドラへ送ります データが入ってくる際 接続されていなければ クライアントが送信を始めた ハンドシェイクでしょう
単にconnection.sendで 同じコンテンツを送り戻せば クライアントに エコーされます そして全ての後続の コールバック上で 残りのアプリケーションに 受信を伝えます フレームはパイプラインに送られ 画面で確認可能です
後続するフレームも 受け取れたら それらがディスプレイに送られ ビデオとして表示されます
これでUDPクライアント UDPサーバは完成です 実演しましょう
クライアントを 携帯電話上で起動し Macのサーバも起動します
今 サーバが立ち上がり デモ版のMacと 表示されています システムにネームを送るよう 命じたからです これは私の携帯電話です 接続をタップすると ビデオフレームが見られます (拍手)
Bonjourサービスに 接続可能な UDPクライアントを 構築しました これでハンドシェイクの送信 待機ができます ビデオフレームをネットワークに 届けることも可能です
サーバ側にできた Bonjourリスナーは サービスを通知し 接続を受信 ハンドシェイクに応答 これらは画面で確認できます 次は データ移行の最適化について トミーがお話しします (拍手) どうも Network.frameworkを 始めるのは簡単です Network.frameworkでの 接続の構築と受け取りの 方法が分かりました Network.frameworkにおける 重要な点は ソケット以上に作業を 最適化する方法を持つことです
アプリケーション内で ネットワーク接続と― 相互作用する基本的な データの送受信を見てみましょう 呼び出し方法は単純ですが 送受信はアプリケーションの 反応速度に影響し バッファリングはデバイスと ネットワークに依存します
では アプリケーションで データを送信してみましょう 先ほどのアプリケーションに 似ていますが こちらはデータを忙しく 生成するものです 今回使用する TCPストリームには あるウインドウが 実装されています その操作方法は?
これが単一フレームを 送る機能で これは生成した データのフレームです
まず connection.sendを呼び出し データを受け渡します ソケットでの送信に慣れているなら ブロッキングソケットを使います 大容量のデータがあったり 空き容量がない場合 スレッドが遮断されるか 接続が消えるまで待機します 非ブロッキングの場合は 全データを送れずに 50バイトずつ分けて 送る場合もあり得ます その場合は多くの状態を 操作しなければいけません
ネットワーク接続なら一度に 全てのデータの送信が可能です 並列処理ができます しかし バックアップ中の 事象には対処が必要です ライブ配信データの速い やりとりのために 大量のデータを送ることは 避けたいからです ここで重要なのは コールバックのブロック contentProcessedです ネットワーク・スタックが データを消費すると起動します 送信が完了または 認識されたとは限りません これはブロッキングソケット・ コールが戻る時間と 非ブロッキングソケット・コールが バイトを消費する時間と同じです
完了ハンドラ上では 2つ確認できます 1つ目はエラーです データ送信中の問題や 多くは全体の接続失敗を意味します
エラーがなければ 生成するデータが他にないか 確認するチャンスです ライブデータのフレームを 生成しているなら 別のビデオストリームから フレームをフェッチしてください これでデータの速度を 調整できます そして非同期の送信コールバックで 接続からデータを抜き それを優雅に操作する ループを形成しました
もう1つ 送信について 注目したいのは UDPアプリケーションに 最適だということです 多くの小さなデータや 個別のパケットを送信するなら connection.batchという機能を 使うことができます 以前 UDPソケットは 1つのパケットしか送信できず 非効率でした つまり 多くの UDPパケットがある時は 異なるシステムコールやコピー コンテキストスイッチがありました しかし ブロックの中で バッチを呼び出せば 好きなだけ送受信が可能です バッチをブロックし終えるまで 接続はデータ処理を阻止します そして データグラムを 一塊として システムに送信を試みます 1回のコンテキストスイッチで インターフェイスに送信 これで効率が上がります
以上が送信です 受信も送信と同様に 非同期です 非同期はバックプレッシャーを 与えてくれます
今回はTCPベースのプロトコルを 持っています これはレコードフォーマットを 読み込むアプリケーションで― よく使われるプロトコルです
プロトコルがデータの長さなどの 情報を伝える― 10バイトの ヘッダを持っているとします ヘッダ コンテンツの順に 読み込むとして コンテンツが 2~3メガバイトだとしましょう 従来のソケットは 10バイトを読み込もうとし 10バイトを受け取るまで 読み込み続けます その後2~3メガバイトを 読み込み アプリケーションとスタックの間で 行き来するでしょう
しかし NWConnectionでは receiveを呼び出す時 受け取りたい最小と 最大のデータを提供します 10バイトを受け取りたいと 明記できるのです 最小でも最大でも10バイトと 言うことができます 接続全体にエラーがあった場合や 10バイトを読み込んだ場合は 呼び戻されるのです そして コンテンツを読み込み データの長さを呼び出せます 2~3メガバイトを 読み込む場合は ボディの読み込みと 同じことをします 読み込む量の 指示を送るだけなので アプリケーションとスタックを 行き来せずに済みます コールバックを 一度するだけです
相互作用を最適化する 素晴らしい方法です
ネットワークパラメータの中でも 高度なオプションを紹介します 送受信をする際の ネットワークの反応を良くしたり 起動時間の改善のために 接続を設定できます まずは WWDCで 何度も話しているECNです ふくそう情報通知機能のことです エンドホストにネットワーク上の 混雑状況を通知させ 接続を円滑にし 速度を うまく調整する方法です これは全てのTCP接続で 標準的に使用できます 設定は不要です 以前はUDPベースの プロトコルを用いた― ECNの使用は困難でした ではECNの使用方法は?
ipMetadataオブジェクトの 作成から始めましょう ECNはIPパケットのフラグに 管理されていて パケットごとに様々なフラグを 設定することができます それを1つに まとめることも可能です コンテキストオブジェクトは 複数のプロトコルのための 全オプションや優先事項を 類型化できます そしてこのコンテキストを 特別なパラメータとして 送信コールへ送ります これを送信する時 生成されるパケットは マークしたかった 全てのフラグを持ちます とても簡単です そして受信する時も 同様のフラグを得られます 受信に関連したコンテキスト オブジェクトを持ち 特定の低レベルのフラグを 読み取れます
同様に サービスクラスもあります これはURLセッションでも 有効なプロパティで トラフィックの 優先順位を定義します そして 送信時にトラフィックが 待ち行列に入る方法や Cisco ファストレーンでの 働きに影響します
サービスクラスのパラメータを 使うことで 接続全体で サービスクラスをマークできます 今回はバックグラウンド サービスクラスを使いましょう 接続の優先順位が 低いことをマークできます ユーザの対話式データは 邪魔したくないため バックグラウンド サービスクラスを推奨します
パケットごとにサービスクラスを マークすることもできます 同じUDPフローの中に 声と信号を発するデータを 両方持った 接続があるとします この場合はipMetadata オブジェクトを作成できます 今回はサービスクラスをマークし コンテキストを添付して送信 これでパケットごとに 優先順位をマークできます
接続を最適化する 別の方法は 往復する回数を 減らすことです 2つの方法を紹介します 1つ目はファストオープンを 有効にすることです TCP Fast OpenはSYNパケットの中に 初期データを送信してくれます そのため ハンドシェイクを 待つ必要がありません
まずはアプリケーションから 接続に対し 初期データを提供することを 取り決めておきます そのために ファストオープンの 許可をマークし 接続を作成します するとstartを呼び出す前に 初期データを送受信できます
データはIdempotentという マーカーに置き換えられました Idempotentはデータを再送しても 安全であることを意味します 初期データが再送されるため 影響がないのです
startを呼び出して接続を立ち上げ 初期データを使って TCP Fast Open内に 送信できるか試します
TCP Fast Openを使った方法を もう1つ紹介します アプリケーションで データを送る必要のない方法です
TCPに加えてTLSを使う場合は TLSの最初のメッセージは ClientHelloです これはTCPの初期データとして 使えます ご自身のFast Openデータを 提供したくない場合は TCPの詳細なオプションから Fast Openを有効にします すると 自動的にTLSから取り込み 接続の確立中に送信します
データの往復を 節約するものがまだあります スチュアートが 前のセッションで話した― Optimistic DNSです これは短い間しか存続せずに 失効したDNSの応答が使えます
さらに新規DNSクエリを行い それらとの接続を試みます もし 以前に受信して失効した アドレスがまだ通用するなら そのDNSのビヘイビアが 許可されます まずこれらのアドレスと 接続を試みます これで新規DNSクエリの 終わりを待つことなく 設定時間を 大幅に削減できます しかし アドレスが変わった場合は 複数の異なる接続を試すため 接続が反応しなければ 新規DNSクエリが戻るのを待ちます そして そのアドレスを 試します サーバの設定に適していれば 単純な方法です 早く接続が確立します
次に話す分野では アプリケーション内で あなたは何もする必要がありません それはURLセッションや Network.framworkが無料の― ユーザ空間ネットワーキングです 昨年 WWDCで発表したもので iOSとtvOSで使用できます これはソケットレイヤーを 完全に回避する場所です スタックの従来のモデルが 何かという話から始めましょう
ネットワークを通して パケットを受け取るとします Wi-Fiのインターフェイスです パケットはドライバに入り TCP 受信バッファに送られます
アプリケーションが パケットを読み取る時 カーネルから データをコピーします TLSの場合は データを暗号化するため もう1つ別の転換をします
では ユーザ空間 ネットワーキングの場合は?
TCPとUDPがアプリケーションの方へ 移動しました どうなるでしょうか? パケットは先ほどと同様に ドライバに入ります しかし それを自動的に集めるよう メモリマップされた領域に 移動しました そして パケットは 自動的に処理され始めます 唯一の転換はTLSのための データの復号化だけです
これでパケットの送受信の CPUの時間を減らせます 特にUDPのような プロトコルでは アプリケーションから パケットの送信を繰り返すでしょう
ではここでビデオをお見せします ここでもUDPの実演で エリックがお見せした― アプリケーションが 使われています
2つのビデオを 同時に流します
左のデバイスはソケットで書かれた アプリケーションから ビデオストリームを 受け取ります 右のデバイスは Network.frameworkで― 書かれたアプリケーションから 同じものを受け取ります ユーザ空間ネットワーキング スタックを活用しましょう
今回は低フレームで非圧縮の ビデオをストリーミングしますが 大量のパケットが 行き来します 実演のために選んだビデオです 送信速度が十分でなくても ビデオのクオリティは下げず 何かをドロップすることは しません 2つのスタックの間の パフォーマンスの違いが よく分かると思います 見てみましょう
全く同じフレームが ネットワークを通り 最速で送られています
右は簡単に 左を追い越しました
右はレシーバー側だけで 30%少ないオーバーヘッドです
左右を比べると UDPパケットを 送受信するのに必要な― CPUの割合に 大きな違いがあるのです 全てのアプリケーションで 同じ結果になるとは言えません 皆さんはすでに 何かを使っているでしょう 大量のパケットの送受信に UDPをお使いであれば Network.frameworkを 試してください CPUの使用率の違いを 計測してほしいのです 満足してもらえるでしょう
最後はネットワークの可動性に 関する問題の解決についてです これはNetwork.frameworkで 解決する重要な領域です まず接続が円滑に スタートするかを確かめます もう一度 説明しましょう waiting状態は ネットワークの切り替えを 処理するために重要です 接続性が不十分であったり DNSやTCPの最中に接続性が 変わったことを示します 接続が確立する前に ネットワークの状態を 確認するようなAPIは 避けてください 接続を急かし 正確な状態を 把握できない可能性があります
モバイルデータ通信の接続を 確認する必要があっても 接続が変わる可能性があるため 確認しないでください 単にNWParameterを使って インターフェイスを制限しましょう
そして ready状態に入ると ネットワークが切り替わった時 一連のイベントがあります
最初のイベントは “接続の実行可能性”です これは接続が有効なルートを持つ インターフェイスから 送受信できることを示します
それを実演するために Wi-Fiネットワークで 接続を開始したとします
その後 ユーザがエレベーターで 電波を失った場合は 接続が実行可能でないことを 知らせるイベントを生じさせます 何をすべきでしょう?
2つあります 1つ目はユーザに接続を 失っていると通知することです 未接続中は データの送受信に失敗します
しかし 接続を 切る必要はありません 最初のWi-Fiインターフェイスが 戻ってくるかもしれません エレベーターから降りて 同じWi-Fiに戻れば再開できます
2つ目は より良いパスを知らせることです
Wi-Fiネットワークと 接続中に 建物を出るとWi-Fiは使えませんが モバイルデータ通信は使えます 2つのことを教えてくれるのです 接続が実行可能でないことと より良いパスが 利用可能であることです この場合は モバイルデータ通信が使えますね
助言しておきます 接続可能な新規接続があれば そちらに乗り換え 再開できるか 確認してください
新規接続が準備できてから 元の接続を閉じます Wi-Fiネットワークが 回復するかもしれませんし モバイルデータ通信が 失敗するかもしれないからです
では 最後のケースです モバイルデータ通信と接続中に 建物に入り Wi-Fiアクセスがある場合です モバイルデータ通信に 問題はありませんが より良いパスが利用可能です
ここで接続を乗り換えるために 新規接続の確立を試し データを移すこともできます これはデータ料金の 節約になります
しかし Wi-Fiに接続するまでは 元の接続を続けてください コードではどう見えるか お見せしましょう これはBooleanを返す viabilityUpdateハンドラです より良いパスを知らせるbetter PathUpdateハンドラもあります
ネットワークの可動性を どう扱うかに対する解決策は マルチパスコネクションの Multipath TCPにあります まずはパラメータに multipathServiceTypeと打ち クライアント上で Multipath TCPを起動します すると接続は自動的に ネットワーク間を行き来できます アプリケーション内での作業は 何も必要ありません これはURLセッションでも 利用可能です
Network.frameworkで 注目したいことがあります それはインターフェイスタイプを 制限すると Multipath TCPが 適用されることです つまり マルチパスコネクションで モバイルデータ通信を避けたい時は 別のWi-Fiネットワークへ 切り替えるのです
そして Multipath TCPは ConnectionViability ハンドラとは異なります こちらはネットワークが変わる度に 自動的に切り替え ネットワークがない時は 接続が実行できなくなります
接続性や実行可能性 MPTCPを待つ間に 期待することがあります ネットワークを手動で確認する SCNetworkReachabilityなどは 自動で確認できるツールに 置き換えてほしいのです しかし 利用可能な ネットワークの種類や 切り替えについて 知りたい場合もあるでしょう そこで NWPathMonitorという 新しいAPIが利用可能です
NWPathMonitorは インターフェイスの状態や 切り替わるタイミングを 知らせてくれます
インターフェイスそれぞれに 接続を作りたい場合は インターフェイスの 繰り返しを許可します ネットワークが切り替わる度に 通知するので 接続したことをユーザに 知らせたい時に便利です 長いフォームに何かを書き込んだり 多くの操作を実行した後で 結局は接続がないと気付く事態は 避けたいでしょう すぐに次の接続を試したい場合は NetworkPathMonitorがお勧めです かつてないほど円滑に ネットワークの切り替えを行う 様子を見ていただきたいです
それではジョシュが Network.frameworkの 導入方法を紹介します (拍手) どうも 新しいAPIを皆様も 気に入ると思います Network.frameworkの 導入について まずは 禁止事項をお伝えします 新しい技術を 最大限に生かすためです
あなたがmacOSをお使いで Network Kernel Extension内で 不可能なことがあれば 我々は代替を提供します ユーザ空間ネットワーキングと 互換性がないものだからです
URLセッションについて 注意喚起をします プロキシ自動設定について FTPとFile URLはサポートされず HTTPとHTTPSだけが サポートされるでしょう
CoreFoundationレイヤーには 避けてほしいAPIが多くあり いずれ廃止されるでしょう さらにCFソケットや― CFStreamCreatePairWithも 避けていただきたいです これらは接続の確立や ユーザ空間ネットワーキングを うまく活用できません しかし Network.frameworkと URLセッションなら 接続性とパフォーマンスを 向上させられます
他にも避けてほしい Foundation APIがあります NSStream NSNetService NSSocketのいずれかを使用するより Network.framworkか URLセッションへ移行してください SCNetworkReachabilityでは WaitforConnectivityの方が 良いモデルです こちらをお勧めします そして WaitforConnectivityより 良い解決策が NWPathMoniterです 次は使ってほしいものに 焦点を当てます 推奨するAPIはURLセッションと Network.frameworkです URLセッションの焦点は HTTPですが Stream TaskはTCPやTLS接続へ シンプルなアクセスを提供します さらに Network.frameworkは TCP TLS UDP DTLSを サポートしています インバウンドとアウトバウンド 接続のリッスンを操作し 可動性を操作する Path Monitorもあります
ぜひNetwork.frameworkを導入し これらを体験してください 皆さんの顧客は 向上した接続に満足し バッテリーが長持ちすることを 喜ぶでしょう
送受信のパフォーマンスを 最適化する操作方法に注目し 実行可能性やルート変更の サポートを受けてください 違いを 感じていただけるでしょう
Network.frameworkが まだサポートしていない UDP Multicastのユースケースが あればお知らせください
質問やリクエストがあれば 歓迎します サポートへ連絡するか 午後2時からと明朝9時からの ラボでお聞きします
URLはこちらです
ラボは昼食後と明朝です ありがとうございました (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。