package j5;
// MCChat.java
// マルチキャストを使ってチャット機能を提供
// 使い方 > java j5.MCChat
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
//==============================================================================
public class MultiCastChat {
// 受信スレッドを作成・実行し,送信を担当
final byte TTL = 1; //同一セグメント内部のみ到達可能とする
final String MULTICASTADDRESS = ("224.0.0.1") ;
// マルチキャストアドレス224.0.0.1はルータを超えない場合のアドレス
int port = 7000;
// マルチキャストチャット用のポート番号,指定がなければ7000 番とします
byte[] buff = new byte[1024]; //送信用バッファ
String myname ="" ; // 利用者名
int nameLength = 0; //利用者名の長さ
MulticastSocket soc = null; // マルチキャストソケット
// InetAddress chatgroup = null; //チャット用アドレス
InetSocketAddress chatgroup;
// コンストラクタ利用者名などを設定します
public MultiCastChat(int portno){
port = portno ; //ポート番号の設定
BufferedReader lineread = new BufferedReader(new InputStreamReader(System.in)) ;
System.out.println("Input your name below!! (下に識別用の名前を入力)") ;
try{
myname = lineread.readLine() ;
} catch(Exception e){
e.printStackTrace() ;
System.exit(1) ;
}
System.out.println("Welcome " + myname + "!") ;
myname = myname + ">" ;
nameLength = (myname.getBytes()).length ;
for(int i = 0;i < nameLength;++i)
buff[i] = (myname.getBytes())[i] ;
}
//-----------------------------------------------------------------------------
public void makeMulticastSocket() {
// MULTICASTADDRESSに対してマルチキャストソケットを作成.
try{
chatgroup = new InetSocketAddress(MULTICASTADDRESS, port);
soc = new MulticastSocket(port) ;
// soc.joinGroup(chatgroup) ;
soc.joinGroup(chatgroup, NetworkInterface.getByIndex(0));
} catch(Exception e){
e.printStackTrace() ;
System.exit(1);
}
} // end of makeMulticastSocket
//-----------------------------------------------------------------------------
public void startListener() {
// スレッド用クラスListenPacketのオブジェクトを生成し,起動.
try{
ListenPacket lisner = new ListenPacket(soc);
Thread lisner_thread = new Thread(lisner);
lisner_thread.start();//受信スレッドの開始
} catch(Exception e){
e.printStackTrace() ;
System.exit(1);
}
} // end of startListener
//-----------------------------------------------------------------------------
public void sendMsgs() {
// マルチキャストパケットの送信を担当.
try{
// 送信ループ
while(true){
int n = System.in.read(buff, nameLength, 1024 - nameLength ) ;
// if (n > 1){ //文字数が少ないときはコピー失敗するのでチェックしない
// byte[] mesonly = Arrays.copyOfRange(buff, nameLength, nameLength+n-1);
//debug for(byte b: mesonly){
//debug System.out.println(b);
//debug }
// String messtr = new String(mesonly); // byte array to string
// if (messtr.equals("exit")) break;
// }
if(n > 0){
DatagramPacket dp = new DatagramPacket(buff, n + nameLength, chatgroup) ;
soc.send(dp) ;
}
else break ;// CTRL+Dは n==0 になるので、ループ終了
// (Enterのみだと改行文字が含まれるため0に
// ならない)
}
} catch(Exception e){
e.printStackTrace() ;
System.exit(1);
}
} // end of sendMsgs
//-----------------------------------------------------------------------------
public void quitGroup() {
// 接続を終了
try{
System.out.println("Connection Closed.") ;
soc.leaveGroup(chatgroup, NetworkInterface.getByIndex(0));
System.exit(0) ;
}
catch(Exception e){
e.printStackTrace() ;
System.exit(1);
}
}
//-----------------------------------------------------------------------------
public static void main(String[] arg){
MultiCastChat c = null ;
int portno = 7000 ;
// コマンドライン引数があれば、使用ポート番号を設定する
if (arg.length >= 1) portno = Integer.parseInt(arg[0]) ;
c = new MultiCastChat(portno) ;
c.makeMulticastSocket() ;
c.startListener() ;
c.sendMsgs() ;
c.quitGroup() ;
}
} // end of class MCChat
//==============================================================================
// ListenPacketクラス
// マルチキャストパケットを受信します
class ListenPacket implements Runnable {
MulticastSocket s = null;
// コンストラクタ: マルチキャストスレッドを受け取ります
public ListenPacket(MulticastSocket soc){
s = soc;
}
// 処理の本体
public void run(){
byte[] buff = new byte[1024] ;
try{
while(true){
DatagramPacket recv = new DatagramPacket(buff,buff.length) ;
s.receive(recv) ;
if(recv.getLength() > 0){
System.out.write(buff,0,recv.getLength()) ;
}
}
} catch(Exception e){
e.printStackTrace() ;
System.exit(1) ;
}
}
} // end of class ListenPacket