質問: true ; } //ハンドラの生成 handler.post(new Runnable(){ public void run(){ if(!error){ edtSend.setText(""); } else { addText("通信失敗しました3"); } }}); }}); thread.start(); } } ```
回答: > > 手始めとして、ソケット通信を2台のスマホで行うためには、 > > > この時点ですでに通信初心者の範疇を超えてしまっており、ひとつふたつの回答で伝えられる範囲とは思えないのですが、せめて知らなければならない範囲だけでも書いてみます。 ``` socket = new Socket(ip, port) ; ``` Socketというのは、Java(Android)でTCP/IPクライアントソケットを扱うために使用します。 TCPというのはIPプロトコルを使って相手と接続し双方向通信を行うためのプロトコルです。 この時点で???であれば、まぁ自分と相手の二人の電話と思ってもいいです。 さて上記のSocket(ip,port)に戻りますが、これはクライアント側(接続を要求する側)が接続先を指定してsocketを作る、という意味になります。 接続先はIPアドレスとポート番号で指定します。相手の電話番号みたいなものです。 相手先がIPアドレスだけでないのは、同じIPアドレスでもさらに複数接続を行えるようにポート番号も必要とするからです。また、目的によってポート番号を変えている場合もあります。 ブラウザでURLを打ち込むときはたいていサーバ名を書きますが、 https://developer.android.com このサーバ名(developer.android.com)はDNSでIPアドレスに変換するとして、じゃぁポート番号書かなくていいかというと、実際には暗黙のポート番号(httpsの場合は443)が指定されたことになっています。 試しに https://developer.android.com:443 としてもちゃんと繋がります。 というわけで、 > > IPアドレスと、ポート番号は何番を入力すればよいのでしょうか? > > > に対する回答は、「接続待ちしているサーバ側のIPアドレスとポート番号」となります。 ここでおそらく「サーバ側ってなに?」ってなっているのではないでしょうか。 Socketの説明に戻りますが、SocketはTCP/IPクライアントソケットを扱うために使用します。 つまり、2台のAndroidデバイスでTCP/IP接続による通信を行いたいのであれば、1台はSocketでも良いですが、もう1台はサーバ側ソケットでなければなりません。 サーバ側ソケットは ServerSocket を使用します。 まずサーバ側のデバイスが ServerSocket で待ち状態になって(ポート番号はその時にサーバ側が決めます)、それに対してクライアント側のデバイスがSocketで接続すれば、めでたく通信開始になります。 > > 1]で行って確認するIPアドレスと、[2]で行うIPアドレスが違うのですが、なぜなのでしょうか? > > > [1]はデバイス側が知っている自分のIPアドレス、 [2]はインターネット側から見たデバイスのIPアドレスです。 なぜ違うのかというと、ネットワークが違うからです。 そのそもIPアドレスはどうやって決まるかというと、「なんらかの申請を行って取得する」場合と、「自動で決めてもらう」場合とあります。[1]も[2も、自動で決めてもらっています。 誰が決めているかというと、[1]はWi-Fiルータ、[2]は契約したプロバイダです。 ほぼすべてのWi-Fiルータは、Wi-Fi接続したデバイスそれぞれにIPアドレス(これは[1])を与えて、またそれらのデバイスからインターネット側に接続要求があった場合はプロバイダから貰っているIPアドレス(これは[2])に変換した上でネット上のサーバと接続する、という仕組みを持っています。 だから[1]と[2]ではIPアドレスが違いますし、仮にWi-Fiで何台もデバイスを繋げてどのデバイスから[2]を表示しても同じIPアドレスになるはずです。 TCP/IPで接続するためには相手先のIPアドレスとポート番号がわかれば良いのですが、インターネット側からWi-Fiルータの内側にいるデバイスに接続するのは困難である(だってIPアドレスわからないんだもん)ということになります。 さらに言えば、[2]で表示されるIPアドレスも「世界で唯一のIPアドレス(固定IPとか言われます)」でない可能性があります。 そうなるといよいよ「IPアドレスわからない」となってきます。 いきなり外界での接続は諦めるとして、Wi-Fiルータの内側に2台ともある場合、つまり2台とも同じWi-Fiルータに繋がっている場合であればどうでしょうか? それでも問題はあります。IPアドレスを与えてくれたのはWi-Fiルータですが、接続先デバイスのIPアドレスはどうやって知るのでしょう? 2台の設定アプリを両方とも目視で確認する、ということでなければ、どうにかして接続先デバイスのIPアドレスを自分で特定しなければなりません。 この処理を「探索」とか「発見」とか呼びますが、「探索」させるための手がかりをお互いに発信(「俺はここにいるよー」、って感じ)して、それをお互いに探索して、見つかったらその相手に接続します。 「俺はここにいるよー」ってのは接続前に行うことですから、接続が前提であるTCPでは無理です。IPを使った通信には、接続しないで通信できるUDPという別のプロトコルがあります。UDPを使い、さらに相手を特定せずスピーカーのように 「俺はここにいるよー」と声を張り上げる仕組みが必要です。 一気に説明しましたが、1万分の1でも伝わったでしょうか? 実のところ2台のデバイスで通信を行いたい場合でも、直接接続するのではなく、別にサーバを用意してサーバを介して通信するのが遥かに簡単ですし、よほどの理由がなければまずそれを薦めます。