リッスン状態のソケットを生成します。IPアドレス、NULLの場合はデフォルトのIPアドレスで取得。ディスクリプターを削除します。ソケットの受信を待ちます。selectでディスクリプターが書き込み可能になるまで待つ。CONNECT(2)を参照した。複雑に見えるが、実際にはTCPのHandshake終了待ちを手動で行っているだけ。タイムアウトにする場合には、一旦ソケットをノンブロック状態にする。この中で書き込み可能になるまで待つ。recvに関しては今の状態でREAD_ONCE_BYTESずつ読み込むのは不可能。その理由は、相手が送ったデータのサイズがわからないためである。recvの方は、プロトコルの実装のところで、READ_ONCE_BYTESずつ読み込む処理を入れる。&tv);}上記のまとめたライブラリで、サンプル2も実装しています。ライブラリとサンプル2の実装は以下のレポジトリーから取得します。次回は、今回まとめたライブラリを利用して、チャットサーバを作成します。キーになるのは、構造体を送受信するので、プロトコルの設計やプロトコルのパックの仕方などの説明が入るのと複数が同時に接続をするので、複数のディスクリプターの場合の管理の仕方が焦点となります。クライアント側は、フレームワーク化をする予定です。機能はシンプルでも構造的には本格的なものを目指しています。*1:Apacheもデフォルトではforkで子プロセスを生成している。tomcatのようにvm上で動いているものはスレッドでも全体が死ぬことはない。SDKを使ってミニ四駆をスマホでコントロールしようiOSR&D事業部の近藤です。先日、ワンダープラネットで社内ハッカソンが開催されました。そのときに発表した、MaBeeeを使ってミニ四駆を音声でコントロールするアプリを作りました。今回はiOSでのMaBeeeに対応したアプリの作り方を紹介しようと思います。MaBeeeとは?単3の乾電池型のIoTデバイスで、Bluetoothでスマートフォンに接続し、乾電池の出力をコントロールすることができます。乾電池の出力の強弱をコントールすることで、おもちゃや家電製品をスマートフォンでできるようになります。非公式ですがSDKも提供されておりMaBeeeを利用したアプリを自分で作ることもできます。MaBeeeの製品情報はこちらhttps://mabeee.mobi/SDKiOS版SDKはこちらhttps://github.com/novars-jp/MaBeeeiOSSDKAndroid版SDKはこちら(今回は使いません)https://github.com/novars-jp/MaBeeeAndroidSDKサンプルコードGithubにサンプルコードがいくつか公開されています。https://github.com/novars-jpMaBeeeを利用したアプリの作り方まずはXcodeで新規プロジェクトを作りましょう。Applicationにしました。GithubからダウンロードしたSDKを解凍しプロジェクトに「MaBeeeSDK.framework」を取り込みます。実装Storyboardボタンを4つ配置します。「はやい!」「ゆっくり」「ストップ」とラベルに設定します。3段階で乾電池の出力をコントロールするように実装します。tagに設定した値はMaBeeeの出力のコントロール用に利用します。0~100で設定します。*)senderMabeeeとiPhoneをbluetoothで接続するための画面を開きます。Storyboadで「Mabeeeに接続ボタン」とIBActionの接続をしておきましょう。*)senderStoryboardで配置した3つの出力調整用のボタンとこのメソッドをIBActionで接続します。ボタンのtagに設定した値を出力のコントロールするための値として利用します。電源オンまずはMaBeeeを装着してミニ四駆の電源スイッチをONにします。この時点ではまだ電池の出力が0の状態なのでミニ四駆は動きません。「MaBeeeに接続」ボタンを押すとMaBeeeとの接続画面が開き、電源の入っているMaBeeeを検索してくれます。見つかったMaBeeeをタップすれば接続完了です。走行!!接続ができたら「はやい!」「ゆっくり」「ストップ」のボタンを押してみましょう。MaBeeeを組み込んだミニ四駆が3段階の速さで動き出します!まとめアプリの実装次第では、加速度センサーや音声入力をトリガーにして操作をすることもできます。アイデア次第でとっても面白い使い方ができるデバイスだと思います。WatchからiPhoneを経由して操作できるようにしてみました。MaBeeeを利用した作品のコンテストなども開催されていますし、ハッカソンのようなイベントに持ち込んで作品を作ってたら楽しいかもしれないですね。社内ハッカソンの様子はWantedlyのこちらの記事で紹介しています。筆者の専門分野でもあり、最近は色んなネットワークのライブラリーーcurl、photonのようなーーが多いので、手作りのクライアントやサーバも少なくなっています。そのために問題が生じてもどのような問題なのか分からず、ライブラリーのパッチをいつまでも待たないといけなくなったり、効率の悪い回避策を入れたりすることになります。オープンソースが今のように発展していない一昔は、こういうライブラリは自前で作ってきたものです。ライブラリーを使うのに慣れている現在のエンジニアさんには難しく思えるのかも知れませんが、実際にポイントを押さえていれば、そこまで難しいものではありません。この連載によって、基本的なソケット通信のやり方を覚え、実戦で応用ができるならばいいと思っています。TCP/IPにおけるOSIの参照モデルについて概要ネットワークプログラミングに興味のある方は、一度は耳にしたことがあると思います。このOSI参照モデルというのは、ISOで策定されたコンピュータの通信機能において、必要であるべき機能を階層化したものです。これは、厳密な規約ではありませんが、ネットワークの実装時に推奨されるモデルです。今は、ほとんどの通信がTCP/IPプロトコル上で動いているので、こういったモデルの意味も薄れていますが、一昔はZModem、AppleTalk、NetBEUI・・・など無数な通信プロトコルがあったためです。7Layersと言います。本章では、TCP/IPプロトコルにおける参照モデルを中心に説明していこうと思っています。ご存知の方々もいらっしゃると思いますが、初めての方はこれだけでは何を意味するのか分からないと思うので、これに関して、わかりやすく説明をしたいと思います。ハードウェア層ある人が面白いことを考えました。パソコンとパソコンをつないで通信をさしょうと思ったわけです。するためには、送受信ができる装置が必要となります。この装置にはモデム、ISDN、ケーブルモデム、イーサネットカードなどがありますが、一旦ここではイーサネットカードのみを想定します。この装置をパソコンに入れてパソコンとパソコン同士をつなぎます。これがハードウェア層となります。データリンク層さて、パソコンとパソコンを繋いだ状態で、AからBへメッセージを送ろうとします。イーサネットカードに何かのデータを書き込みと読み取りができないと行けません。そこで、イーサネットカードのバッファーにデータを書き込み・読み込むモジュールを作成しました。保護モードで動くOSでは、デバイスドライバーに当てはまります。このドライバーの書き込みや読み込みの機能がデータリンク層*1になります。基本、データリンク層ではハードウェア層にリクエストを投げることになります。ネットワーク層ただ、これだけでは面白くありません。今度は複数のパソコンに繋いで見たくなりました。するためには、送り先を指定しなければなりません。パソコンに住所をつけることにしました。protocol)です。ipアドレスというのは、ipヘッダーの識別子になります。いうわけで、デバイスの方にipprotocolを実装し、転送するようにしました。送信パケットにipヘッダーをつけて、送り先のアドレスと一緒に送信するような感じです。この場合、送信先までに送るための中継機器が必要となります。その機器をルーターとしておきます。一方で、受信する側のパソコンでは、自分のipアドレスのみ*3を受信できるようになります。このデバイスドライバーのipプロトコルの実装と中継機器がネットワーク層になります。ちなみにpingはこのネットワーク層までで動いています。ネットワーク層ではデータリンク層にリクエストを投げるようになります。トランスポート層これで複数のパソコンで通信ができるようになりました。面白いことがしたいところです。パソコン同士でチャットをしたり、ファイルのやりとりを同時にやりたい。ipプロトコルだけでは、どれがチャットのメッセージでどれがファイルのメッセージなのか区別がつきません。そこで工夫された一つの規約がTCPプロトコルです。ポート番号を設け、デバイスに届くデータを振り分ける仕組みです。TCPプロトコルをデバイスに実装しました。*4なので、データを送る際にTCPヘッダー+実データにして、ネットワーク層へ要求を出すことになります。この機能がネットワーク層とトランスポート層に当てはまります。このトランスポート層では、データのロスを防ぐために、データが失われた場合は、再要求を送信したりするような機能も実装してあります。トランスポート層では基本的にネットワーク層にリクエストを投げるようになります。セッション層これで、パソコン同士が通信ができるようになりました。LANケーブルはノイズがあり、データが失われたり、接続が不安定なことが多いです。その接続の回復などの処理ーー通信の再送とは別ーーを行う機能を追加しており、この処理を行うのがセッション層であります。*5TCP/IPにおいて、ハードウェア層からセッション層までは全てハードウェアとデバイスドライバーの内部の話になります。実際にこの階層で綺麗に分かれているような実装になっているかどうかは不明ですが。プレゼンテーション層というのは、アプリ層の方で、プレゼンテーション層へ要求を出す際に形式的な変換ーー例えば、文字コードの変換ーーのような事をしますが、TCP/IPにおいて、プレゼンテーション層というのは、デバイスドライバーの方で対応することが難しいです。TCP/IPの上に色んなプロトコルが存在するために一概に処理をすることができないためです。TCP/IPのネットワークプログラミングの話は主にプレゼンテーション層とアプリ層の話になります。抽象的で分かりづらいとは思いますが、実際にソケットプログラミングをすると分かってくるかと思います。最後に次回の話のための何を使ってソケット通信のプログラムをするかを説明したいと思います。Socketネットワークデバイスでは、以下のようなインターフェースを提供しています。Socketと言います。Unixに初めて実装され、今はほとんどのOSで採用されています。socketopenと同じようにdescriptorを生成します。ファイルと同じくdescriptorはi-nodeとして管理されます。closesocketで生成されたdescriptorを解放します。send/writeデータを送信します。ファイルと同じくwriteもサポートしていますが、ioctlなどで調整が必要となります。sendを使う方をお勧めします。recv/readデータを受信します。ioctl/fctlソケットの受信をnon-block状態にしたり、送信時のバッファーを設定したり、ブロードキャストの設定をしたり細かい設定を行うためのインターフェース。OSの実装の仕方によって、どれをどう使うかになります。どちらも使えますが、OSによっては片方しか使えなかったりします。select設定したdescriptorから何か変化があるまで、スレッドをスリープ状態にします。ストリーム(TCPのコネクション型時の追加のシステムコール)connectリモートと接続*6を計ります。bindポート番号とdescriptorを結びつけます。listenクライアントのconnectを待ちます。acceptlistenから接続が確立したセッションに対してdescriptorを生成します。ソケットプログラミングにおいて、使うのはは上記のシステムコールのみとなります。今回は文章が多く退屈だったかと思いますが、次回では簡単なクライアントとサーバのプログラムを作成したいと思います。*1:厳密には、イーサネットカードのヘッダーも含まれる*2:ipアドレスなしでどのように通信を行うのか疑問に思う方もいると思うので説明すると、そういう場合はMACアドレスやドメイン名などで通信することになります。ローカル内での通信までしかできない*3:今のスウィッチングハブは、違うipアドレスの機器には転送しないが、その前まではつながっている全ての機器に送信していたの>で、各機器の方で違うipアドレスのパケットを弾く処理を行なっていた。*4:デバイスドライバーの実装はここから複雑になっていく*5:TCP/IPプロトコルに置いては、セッション層はデバイスの方ではそんなに処理がない。21:04C/C++でネットワークプログラミングをしてみよう(1)Tweet次のページ採用情報ワンダープラネットではモバイルゲーム開発者を募集しております。(S編)C/C++でネットワークプログラミングをやってみよう(2)スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。