目次
プロセス間通信の必要性
大規模なソフトウェアを作成しようとすると、
プロセス間通信の機能が欲しくなります。
複数のソフト(プロセス)を同時に走らせ、
それらのプロセスがデータを通信しあうことによって、
複数のプログラムによる協調駆動を元にした
大規模ソフトを作成することができるのです。
またこのような
プロセス間通信を元にした
ソフトウェアの設計をすることにより、
ソフトウェアのモジュール化が進み、
ソフトの再利用性が向上したり、
マルチコアやハイパースレッディングに対応した
最近のCPUのリソースを最大限に利用することができます。
また、今回紹介するTCP/IPのソケット通信などを利用することにより
複数台のコンピュータに跨るソフトウェアを作成することができ、
ハードウェアを抽象化するソフトも作成することができます。
TCPを使用したプロセス間通信
プロセス間通信を実現する方法はいくつかありますが、
その内一つはTCP/UDPを使用した方法です。
TCP/UDPは現在のインターネットで採用されている
通信プロトコルで、
インターネットに接続できないPCが殆どいないのと同様に
TCP/UDPを使用することができないPCは殆どいないといえるほど
一般的な方法です。
その中でもTCPは、データの送受信の管理や
データの抜けや順番のチェックなど
通信をする上で一番面倒な部分を
すべてTCP自身が実施してくれるプロトコルです。
ユーザは通信のことを考えなくて良くなり、
メインのアプリに集中することができます。
詳しいTCPの概要に関しては冒頭の参考文献を
参考にしてもらいたいと思います。
(ちなみ冒頭の本は、
TCP/IPだけの本かと思われますが
コンピュータによる通信のバイブルと言われるほどの
名著で、わかりやすく非常にオススメです)
C++でTCP通信用ライブラリの使い方
今回、Linuxにおいて、
C++によるTCP通信用のライブラリを作成してみました。
この記事の一番下にGist上のコードを載せておきます。
コードを見ると分かる通り、
TCPのサーバ用のクラスとクライアント用のクラスが定義されている
ヘッダライブラリです。
ヘッダライブラリなので、インクルードするだけで使用できます。
使い方はそれぞれのクラスのヘッダコメントに書いてありますが、
まず初めにプロセス間通信をしたい2つのプログラムを準備し、
片方をサーバとして、サーバクラスを下記のように使用します。
TcpServer server;//TCPサーバ用オブジェクト int PORT=50001;//サーバのポート番号 server.Init(PORT);//初期化
ポート番号はプログラムの名前みたいなものなので、
自由に使用可能な49152–65535の中で一つの値を選びます。
TCPやUDPにおけるポート番号の一覧 - Wikipedia
するとサーバ側がクライアントのコネクト待ち状態になります。
続いて、もう片方のプログラムをクライアントとして、
クライアントクラスを下記のように使用します。
TcpClient client;//TCPクライアント用オブジェクトの作成 string LOCALHOST="127.0.0.1";//ローカルホストのIPアドレス int PORT=50001;//ポート番号 client.Init(LOCALHOST,PORT);
この例では、サーバプログラムもクライアントプログラムも
同一のPC内で起動していることとして、
サーバのIPアドレスとローカルホスト(自分自身のPCのIPアドレス)
としています。
また、ポート番号は当然、先ほどのサーバプログラムで指定した
番号と同じものにしなければなりません。
続いてクライアントとサーバが無事接続された場合、
あとは、サーバでもクライアントでも
下記のようにデータを送受信できます。
サーバ:
vector<char> ReadData; int nSend=server.Send(data); //受信 vector<char> SendData; SendData.push_back(0x01);//0x01というデータを送る int nWrite=server.Write(data);//送信
クライアント:
vector<char> ReadData; int nSend=client.Send(data); //受信 vector<char> SendData; SendData.push_back(0x01);//0x01というデータを送る int nWrite=client.Write(data);//送信
便利ですね。
初めてこの方法で通信出来た時はちょっと感動しました(笑)。
また、先ほどの例のクライアントのIPアドレス指定部分を、
適切に設定してあげるだけで、違うPC同士の通信もできます。
Javaでのソケット通信
Javaでソケット通信をする場合は、
- TCP: Socket.ServerSocket
- UDP: DtagramSocket
というクラスを使います。
ソケット通信のエラーの確認方法
ソケットの関数である,readやwrite,bindなどは、
返り値によってエラーを判断できますが、
ただの数字なので、どのようなエラーが発生したのかがわかりにくいです。
そんな時は下記のライブラリのように、
エラー判定のif文内で、システム関数であるperror関数を呼ぶことで、
発生したエラーに応じて、エラーメッセージが標準エラー出力に出力されます。
perrorの引数である文字列は、
エラーメッセージが表示される時に先頭に表示される文字列で、
エラー判定した関数名とかにしておくと、
どの関数でエラーが発生したのかがわかりやすくなります。
あとは、もしなにかエラーが発生したら、
そのエラーメッセージを読むなり、ぐぐるなりで
対応できるようになると思います。
Address already in use というエラーが発生した場合
うまくソケットの設定を行わないとこのエラーがでます。
Geekなぺーじ:TCPを使う(サーバ、SO_REUSEADDR)
Programming UNIX Sockets in C - Frequently Asked Questions: サーバアプリケーションの作成 (TCP/SOCK_STREAM)
もし出てしまった場合は、5分ほど待つか(おそらく自動で解除されるはず)
下記の方法で、プロセスを殺します。
特定のポートを使用してるプロセスを調べてkillするときの手順メモ。 - NOT SO BAD
下記のコマンドでポートを占有しているプロセスを見つけて、
(0000には作成中のソフトのポート番号を入れます)
lsof -i :0000
その中からPID(下記の例では111)を見つけて、
killします。
kill 111
そして、もう一度ソフトを起動すれば、先程のエラーは出なくなるはずです。