スマホアプリにおけるプロセス(スレッド)間通信方法
スマホアプリにおけるプロセス(スレッド)間通信方法
プロセスとスレッドはそのコンテキストを共有するかどうかが異なるだけで、同一時間に複数の手続きを実行させるということにおいて概念的には同じである。
スレッド間で通信を行うには次の方法がある。
どの方法も50年前にC言語とともに生まれた偉大なOSであるUnixから実装されているレガシーな方法である。
・共有メモリ
POSIX標準の共有メモリはiOS、androidともに使用できない。
スレッド間であれば、インスタンス変数を共有することができる。
iOS
セマフォと合わせて使い、インスタンス変数(ヒープ領域)を共有する。
POSIX標準のshmget()等は使用できないため、アプリ間で共有するには、カスタムURLスキームやApp Groups#NSUserDefaultsやUIPasteboardなどのCocoaフレームワークで用意されている仕組みを利用する必要がある。
android
インスタンス変数が格納されるヒープメモリのGC(ガーベージコレクション)の影響やヒープメモリキャッシュの影響などによりThread間でメモリ領域を共有する際に想定外の動作をする場合があるので注意が必要となる。
・セマフォ
iOS
mSemaphoreForTerminate = dispatch_semaphore_create(0);dispatch_semaphore_signal(mSemaphoreForTerminate);
android
mSemaphoreForTerminate = new Semaphore(0);
mSemaphoreForTerminate.release();
・シグナル
try catch構文でエラー手続きに活用されているシグナルだが、本来はプロセス間通信のために作られた機能である。
スレッド間通信で用いるには、OSがSIG...として定義していないシグナル領域を用いる。
iOS
NSCondition#signal
android
使用できない
・androidフレームワークで用意されているスレッド間通信方式
スレッドとServiceConnectionをbindServiceで関連づけ、Messengerで双方向のスレッド間通信を実現する。
android
android#content#ServiceConnection // 送受信のInlet Outletandroid#content#ContentWrapper#bindServiceandroid#os#Message msg = Message.obtain();
msg.arg1 = NOTIFICATION;
msg.replyTo = SelfMessenger;
android#os#Messenger#send(msg);
・ソケット
iOS
iOSではPOSIX標準ソケットとCocoaフレームワークのソケットが利用できる。
1) POSIX socket
int ipv4_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)listen()
2) CFSocket
CFSocketRef myipv4cfsock = CFSocketCreateCFRunLoopAddSource()
android
Socket socket = new Socket();socket.connect(new InetSocketAddress(IP_SERVER, SOCKET_SERVER), CONNECT_TIMEOUT);OutputStream outputStream = socket.getOutputStream();// リクエスト送信byte[] requestBuffer = "Request String".getBytes("UTF-8");outputStream.write(requestBuffer, 0, requestBuffer.length);// リクエスト受信while(true) { String requestString = readSocket(socket, inputStream, outputStream);}