- ベストアンサー
javaのudp通信について
- javaのudp通信を使用して簡単なチャットプログラムを作成する方法を紹介します。
- 送信、受信それぞれのプログラムはできましたが、それをひとつに統合する方法についても解説します。
- また、受信プログラムの詳細として、受信データを処理する方法についても説明します。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
import java.net.InetAddress; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.net.UnknownHostException; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; /* GUIは詳しくないので、スレッドを使ったプログラム例です。 応用すれば、送信テキストエリアと受信テキストエリアを持つ、 GUIプログラムが書けると思います。 Usage : java udp peerhost peerport myport peerhost 接続先ホスト名 peerport 接続先ポート番号 myport 接続待ちポート番号 使用例 1.ローカルループバックでテスト ターミナルを2つ用意する (terminalA) java udp localhost 60000 61000 (terminalB) java udp localhost 61000 60000 2.ホスト間 (hostA側) java udp hostB 60000 61000 (hostB:60000に送信 自分は61000で受信) (hostB側) java udp hostA 61000 60000 (hostA:61000に送信 自分は60000で受信) */ public class udp { public static void main(String [] args) throws Exception { String peerhost = args[0]; int peerport = Integer.parseInt(args[1]); int myport = Integer.parseInt(args[2]); System.out.println("connec to " + peerhost + " " + peerport); System.out.println("receive at " + myport); SendThread s = new SendThread(peerport , InetAddress.getByName(peerhost)); ReceiveThread r = new ReceiveThread(myport); s.start(); r.start(); s.join(); r.join(); } } /* 送信スレッド 標準入力から読み取り、指定のアドレス宛に送信 */ class SendThread extends Thread { Sender s; public SendThread(int port , InetAddress addr) throws SocketException { this.s = new Sender(port , addr); } public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while(true) { String msg = ""; try { msg = br.readLine(); /*ここをテキストエリアから読み取る様に変更*/ this.s.send(msg); } catch(IOException e) { e.printStackTrace(); } } this.s.close(); } } /* UDP送信クラス */ class Sender { private int port; private InetAddress addr; private DatagramSocket sock; public Sender(int port , InetAddress addr) throws SocketException { this.port = port; this.addr = addr; sock = new DatagramSocket(); } public void send(String msg) throws IOException { byte buf [] = msg.getBytes(); DatagramPacket packet = new DatagramPacket(buf , 0 , buf.length , this.addr , this.port); this.sock.send(packet); } public void close() { this.port = 0; this.addr = null; this.sock.close(); this.sock = null; } } /* 受信スレッド 繰り返し受信し、標準出力に書き込み */ class ReceiveThread extends Thread { Receiver r; public ReceiveThread(int port) throws SocketException { this.r = new Receiver(port); } public void run() { while(true) { String msg = ""; try { msg = this.r.recv(80); System.out.println(msg); /*ここをテキストエリアに書き込む様に変更*/ } catch(IOException e) { e.printStackTrace(); } } this.r.close(); } } /* UDP受信クラス */ class Receiver { private DatagramSocket sock; public Receiver(int port) throws SocketException { this.sock = new DatagramSocket(port); } public String recv(int length) throws IOException { byte [] buf = new byte[length]; DatagramPacket p = new DatagramPacket(buf , length); this.sock.receive(p); return new String(p.getData() , 0 , p.getLength()); } public void close() { this.sock.close(); this.sock = null; } }
その他の回答 (2)
>this.r.close();とthis.s.close()で到達不能エラーが出てしまうのですが、環境の違いにようものでしょうか? 私の環境ではこのエラーは出ませんね… versionは javac/java 1.5.0 です。 while(true)ブロック内にbreak文が無いため、ループを抜ける手段が存在しないためのコンパイルエラーと思われます。 適切な終了条件(文字列"exit"を受信/送信したらbreakする、等)を設定すればこのエラーは消せると思います。 >また、ソケットやポート、アドレスなどを初期値として設定してSenderメソッド、クラスやReciveメソッド、クラスmainクラスなどから呼び出すことは可能でしょうか? これはもちろん可能でしょう。 簡単にやるならば、ソース中に埋め込んでしまえば良いかと。 >今回ご指導いただいてイメージとして大きく分けて、送信、受信メソッド(クラス)そしてmainのクラスを作り、スレッド操作したいと考えました。考え方はいかがでしょうか? 良いと思います。 コーディングの基本はわかりやすくなるまで細分化です。 機能単位でまとまったクラスを用意し、それらを組み合わせて目的を達することが肝要です。
>送信、受信それぞれのプログラムはできました。送信は送信を繰り返し、受信も受信を繰り返すものです。それをひとつにしたいと考えています。 コンピュータ間でチャットを行うというのが目的ですよね。 送信、受信のプログラムができたのならば、目的は達せられたのでは? 「ひとつにする」の意味がわからないのですが、 これは単一のプログラム内でループバックデバイスに対し 送受信を行うというようなことを目標としているのですか? (これは「チャット」とは呼べないような…) それともコマンドライン引数などで実行時の送信・受信動作を切り替える、 というようなことを目標としているのですか? (これならば、2つのプログラムを単純にくっつければ良いでしょう。) もしくは全く別の意図があるのですか?
補足
説明不足で申し訳ありません。 今回の課題の目的として、送受信の出来るチャットプログラムの製作という題名なので課題の意図に2つのプログラムを一つにまとめることができるかがあるみたいです。 こうゆう事は初めてでどうしていいか。。。といったのが現状です。 *プログラムの詳細* ・javaのUDP通信の使用 ・サーバーは使用しない ・送受信を繰り返し行う ・画面の製作(←これはSwingでなんとか作ってみました) プログラムの流れは、起動→受信待ち→受信→textに追加→送信→textに追加→受信待ち という感じです。送信はユーザーの任意で行えるものにしたいと考えています。 まだご不明な点などありましたらご指摘お願いします。
補足
this.r.close();とthis.s.close()で到達不能エラーが出てしまうのですが、環境の違いにようものでしょうか? また、ソケットやポート、アドレスなどを初期値として設定してSenderメソッド、クラスやReciveメソッド、クラスmainクラスなどから呼び出すことは可能でしょうか? 今回ご指導いただいてイメージとして大きく分けて、送信、受信メソッド(クラス)そしてmainのクラスを作り、スレッド操作したいと考えました。考え方はいかがでしょうか?