マルチチャットルームの実現構想分析


通信に関する知識点を復習した後、私たちは「マルチチャットルーム」の小さなプロジェクトの練習を完成しなければなりません.このプロジェクトは通信、スレッド、イベントの傍受とグラフィックのプログラミングに関する概念に関連しています.一見簡単だと思いますが、グラフィックインタフェースを追加するのではないでしょうか.后で実现する时そうではないことを発见して、ほとんど寸歩が难しくて、少し焦って、しかし急いでも役に立たないで、プログラムというものは人が心を静めて考えてやっと结果を得ることができます.そこで私は心を静めて考え始めました.
まず、複数のチャットルームを書きます.これは、私のServer socketクラスがaccept()メソッドを一度だけ呼び出すことができないことを意味します.そこで、最初の質問をメモします.
1従来のシングルチャットプログラムよりも、今回のサーバソケットで対応する処理が必要
私の対応する解決策はスレッドを使うことで、私はRunnableインタフェースを実現したMyThreadクラスを作成して、それからsocketを受信した後のステップについて私の書いたスレッドクラスに渡して処理して、コードの部分は以下の通りです

   while(true)
			{Socket socket=serverSocket.accept();
		 //         
			MyThread mt=new MyThread(socket);
			vs.add(socket);
			mt.start();
							
			}	
  
2マルチチャットルームである以上、サーバがここで果たす役割は、受信したメッセージをすべてのクライアントに転送するブロードキャストであるべきであるので、ここでサーバはすべてのクライアントのsocketを取得し、読み出した情報を各ユーザにループ送信し、私が使っている方法は、すべてのサーバがクライアントに対して作成したスレッド(すなわち、すべてのMyThread)を格納するために静的ベクトルを使用し、情報を送信するときにこのベクトルを使用してsocketを取り出すことです.具体的なコードは以下の通りです.
public static Vector<Socket> vs=new Vector<Socket>();
public void run() {
		//           
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			PrintWriter pw ;
			//           ID 
			Random rand = new Random();
			int idone = rand.nextInt(1000);
			String msg;

			while (true) {//           
				msg = br.readLine();
				System.out.println(idone + " :" + msg);
				//         socket  
				for(int i=0;i<Server.vs.size();i++)
				{	Socket so=Server.vs.get(i);
				pw=new PrintWriter(so.getOutputStream(), true);
				pw.println(idone + " :" + msg);
				}
				
				

			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

3サーバ側の問題を解決しました.次にクライアントの問題です.まず最初の問題はインタフェースの問題です.
この問題は解決しやすいので、以前書いたとおりにすればいいです(私が書いたクライアントクラスはJFrameというクラスを継承しているので、コードにはthis.*がたくさんあります)
//        
		this.setSize(600, 500);
		jt = new JTextArea();
		jt.setLineWrap(true);
		jt.setEditable(false);
		jt.setText("");
		jb = new JButton("  ");
		jb.addActionListener(this);
		jf = new JTextField(25);
		mp = new JPanel();
		//             
		mp.add(jf);
		mp.add(jb);
		//        
		jp = new JScrollPane(jt, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		this.add(jp, "Center");
		this.add(mp, "South");
		this.setLocationRelativeTo(null);
		this.setVisible(true);

4クライアントのインタフェースの問題は解決して、それから最も肝心な問題で、どのようにサーバーのフィードバックのデータを得ますか?
この問題は長い間考えていました.私はその中の1つの問題で長い間悩んでいたので、いったいいつsocketを使うべきですか.getInputStream()このメソッドは入力ストリームを取得し、データを読みますか?
私が実験した答えは意外でした.答えはsocketオブジェクトを手に入れたら、いつでもいいです.つまり、readline()メソッド(ここではBufferedReaderオブジェクトを使用しています)をいつでも実行したいと思っています.私が心配している理由は、readline()メソッドを実行するときにサーバがデータを送信していないか、クライアントがデータを送信していない場合、プログラムはどのように対応するのかということです.そのために私はわざわざ実験をしました.
public void run() {
		//                      
		String msg;
		while (true) {
			try {
				Thread.sleep(300);
				//         
				msg=br.readLine();
				System.out.println("msg"+msg);
				
				if (!(msg.equals(""))) {
					//            ,          
				//	JOptionPane.showMessageDialog(null, jf.getText());
					jt.append(msg + "
"); jt.setCaretPosition(jt.getText().length()); // jf.setText(""); } } catch (Exception e) { e.printStackTrace(); } } }

上は私が書いたサーバーからメッセージが届いたかどうかを常に傍受するためのスレッドrun()メソッドで、whileサイクルで読み取った文字列をreadline()メソッドで変数msgに格納し、印刷します.このスレッドの睡眠時間は300 msで、私の考えでは一連の空の文字列を印刷しているはずです.その結果、文字列を受信してからプログラムが実行されるのを見て、私は結果がすぐに開いたのを見て、データを読むときにプログラムが実行されるのではなく、ブロック状態になっていたので、私が心配していた大きな問題は基本的にすべて解決されました.
ここまで考えてみると、私の考えはもうはっきりしていたので、楽な状態でプロジェクト全体を書き終えました.
まとめ:一つのプロジェクトを書く前に、まず心を静めて考え、必要な各知識点を考慮し、どのように分布して実現し、それから一歩実現しなければならないのか、発散的な思考よりも効率的です.
添付ファイルにはこのプロジェクトのソースコードがあります