66ネットワークプログラミング(5) - TCPマルチスレッドマルチチャットルーム

思考

  • クライアントは、内部クラスはRunnableをを達成することができ、それぞれのクラスを記述します。読むのクラスは、巻き取り、髪をサーバ側との接続を確立します。
  • クライアントが受信して転送します。各クライアントの接続(クライアント依存しないとの接続)を達成するためにマルチスレッド。
  • メッセージを格納するためのサーバー側の共通バッファプールを作成します。方法サーバーを転送することで、クライアントに転送されます。

クライアントコード

_20191218パッケージ; 
インポートにjava.io.DataInputStream; 
インポートjava.io.DataOutputStreamのメソッド、
インポートにjava.io.IOException; 
インポートのjava.net.Socket; 
インポートjava.net.UnknownHostExceptionを発行; 
インポートjava.util.Scanner; 

/ ** 
 *マルチマルチスレッド達成するためにチャットルーム、クライアント、送信、リアルタイムでデータを受信し、
 * / 

publicクラスTCPMultipleChatClient { 
	公共の静的な無効メイン(文字列[] args){ 
		System.out.printlnは(「LANチャットルームに------- ----------- "); 
		スキャナSCAN1は新しい新しいスキャナ(System.in)を=; 
		System.out.printは("あなたのニックネームを入力してください:「); 
		文字列名= scan1.nextLine(); 
		文字列のアドレス= "176.195.108.53"; //サーバのアドレス
		int型ポート= 6788; //サーバプログラムポート
		ソケットクライアント= NULL; 
		試し{
			ソケットは、新しい新しいクライアント(アドレス、ポート)=; 
			System.out.printlnはは(「成功したあなたがチャットを開始することができ、ログイン!」); 
			System.out.printlnは(「--------------- --------- "); 
		}キャッチ(UnknownHostExceptionがE){ 
			System.err.println("サーバ接続失敗"); 
		}キャッチ(IOExceptionをE){ 
			System.err.println("サーバ接続失敗」 ); 
		} 
		/ ** 
		 *開始するための受信機と送信機
		 * / 
		新しい新しいスレッドを(新しい新しい送信者(クライアント)、ユーザ名).start(); 
		新しい新しいスレッド(新しい新しい受信機(クライアント))開始();. 
	} 
} 
	//送信:実装のRunnable 
	クラスの送信者を実装したRunnable { 
		trueにプライベート=ブールのフラグ; //サーバの生存をtrueにした
		//出力ストリーム
		プライベートDataOutputStreamのドス。 
			{みてください 
		//コンストラクタ:初期化
		公衆送信者(ソケットクライアント){ 
				DOS =新しいDataOutputStreamを(client.getOutputStream())。
			}キャッチ(IOExceptionを電子){ 
				System.err.println( "服务器未开启、连接失败")。
			} 
		} 
		公共ボイドのsendMessage(){ 
			スキャナスキャン=新しいスキャナ(System.in)。
			文字列メッセージ= scan.nextLine()。
			試す{ 
				dos.writeUTF(にThread.currentThread()のgetName()+ ":" +メッセージ)。
				dos.flush(); 
			}キャッチ(IOExceptionを電子){ 
				System.err.println( "送信者:服务器关闭")。
				フラグ= falseは、
			} 
		} 
		公共ボイドラン(){ 
			一方(フラグ){ 
				のsendMessage()。
				{試みる
					のThread.sleep(500)。 
				}キャッチ(InterruptedExceptionある電子){ 
					e.printStackTrace(); 
				} 
			} 
		}
	} 
	//受信機:Runnableを実装する
	実装のRunnable {レシーバクラス
		trueにプライベート=ブールのフラグを; //サーバの生存をtrueにした
		//入力ストリーム
		、プライベートDataInputStreamをDIS 
		公共レシーバー(ソケットクライアント){ 
			試み{ 
				DIS =新しい新しいDataInputStreamの(client.getInputStream ()); 
			}キャッチ(IOExceptionをE){ 
				e.printStackTrace(); 
			} 
		} 
		//メッセージの読み取り
		パブリックボイドReadMessageを(){ 
			試み{ 
				のSystem.out.println(dis.readUTF()); 
			}キャッチ(IOExceptionをE ){ 
				ReadMessage(); 
				試み{ 
				System.err.println( "reciver:サーバを閉じます")。
				フラグ= falseは、
			} 
		} 
		公共ボイドラン(){ 
			一方(フラグ){
					Thread.sleep(500)。
				}キャッチ(InterruptedExceptionある電子){ 
					e.printStackTrace(); 
				} 
			} 
		} 
	} 
//}

  

サーバー側のコード

_20191218パッケージ; 

インポートにjava.io.DataInputStream; 
インポートjava.io.DataOutputStreamのメソッド、
インポートにjava.io.IOException; 
インポートjava.net.ServerSocket; 
インポートのjava.net.Socket; 
インポートjava.util.Scanner; 

/ ** 
 *マルチチャットルーム、サーバー、リアルタイムのデータ転送
 * / 
publicクラスTCPMultipleChatServer { 
	公共の静的な無効メイン(文字列[] args){ 
		System.out.printlnは( "サーバーオープン"); 
		//サーバー側を作成する
		ServerSocketをサーバー= NULL; 
		{トライ
			サーバ新しい新しい= ServerSocketを(6788); //サーバポート
		}キャッチ(IOExceptionをE){ 
			e.printStackTrace(); 
		} 
		//コンテナ
		コンテナコンテナコンテナ新しい新=(); 
		//ループ聴取
		しばらく(真の){ 
			接続要求のための//リッスンがブロックされて
			試してみる{ 
				ソケット= server.acceptクライアントを(); 
				System.out.printlnは(「ユーザを正常に接続する」); 
				container.doCount(); 
				//開いている受信機
				の新しいスレッド(新しい新しい受信機(クライアント、コンテナ))スタート();. 
				//オープントランスポンダ
				新しい新しいスレッド(新しい新しい送信(クライアント、コンテナ))スタート();. 
			}キャッチ(IOExceptionをE){ 
				e.printStackTrace(); 
			} 
		} 
	} 
	
	静的クラスコンテナ{ 
// = StringBufferの新しい新しいラップのStringBuffer(); 
		静的INT USERCOUNT = 0;ユーザーの//現在の数
		プライベートINT今= 0; //量が転送された
		プライベート文字列[] STRS =新しいString [1024]; / /メッセージ・キュー
		//メッセージカウンタ;プライベートint型iは0を=
		公共ボイド追加(文字列メッセージ){ 
				DISが新しいのDataInputStreamを=(client.getInputStream()); 
			STRの[I] =メッセージ; 
			I ++。
		} 
		パブリック静的ボイドdoCount(){//用户量加一
			USERCOUNT ++。
		} 
		公共ボイドsubUserCount(){//用户量减一
			userCount--。
		} 
		公共ボイドリセット(){ 
			IF(今== USERCOUNT){ 
				STRS =新しいString [1024]。
				今= 0; 
			} 
		} 
	} 
	静的クラスレシーバ実装のRunnable { 
		プライベートブーリアンフラグ= TRUE。
		プライベートコンテナコンテナ。
		民間のDataInputStreamをDIS; 
		公共レシーバ(ソケットクライアント、コンテナ容器){ 
			this.container =コンテナ。
			試す{ 
			}キャッチ(IOExceptionを電子){ 
				e.printStackTrace(); 
			} 
		}
		//读取消息
		ます。public void readMessage(){ 
			試み{ 
				//存入容器
				文字列str = ""; 
				(!。(STR = dis.readUTF())等号( "")){場合
					Container.addの(文字列); 
				} 
				
			}キャッチ(IOExceptionを電子){ 
				フラグ= FALSE。
				System.err.println( "読む:用户已离开会话"); 
				container.subUserCount(); 
			} 
		} 
		公共ボイドラン(){ 
			一方(フラグ){ 
				readMessage()。
			} 
		} 
	} 
	//转发
	静的クラス送信器具のRunnable { 
		プライベートブーリアンフラグ= TRUE。
		プライベートコンテナコンテナ。
		プライベートDataOutputStreamのドス。
		公衆送信(ソケットクライアント、コンテナ容器){
			this.container =コンテナ。
			試す{ 
				this.dos =新しいDataOutputStreamを(client.getOutputStream()); 
			}キャッチ(IOExceptionを電子){ 
				フラグ= FALSE。
				System.err.println( "送信:用户已离开会话"); 
			} 
		} 

		公共ボイドラン(){ 
			一方(フラグ){ 
				送信()。
				{試みる
					のThread.sleep(500)。
				}キャッチ(InterruptedExceptionある電子){ 
					e.printStackTrace(); 
				} 
			} 
		} 
		公共ボイド送信(){ 
			(文字列str:container.strs)は{ 
				{試みる
					場合(STR == NULL){ 
						続けます。
					}
					System.out.println( "已转发消息:" + STR); 
					container.now ++; 
					dos.writeUTF(STR); 
					dos.flush(); 
				}キャッチ(IOExceptionをE){ 
					e.printStackTrace(); 
				} 
			} 
			コンテナ。リセット(); //転送後消去
			
		} 
	} 
}

  

ショー

実行しているサーバーは、複数のクライアントを実行します。

おすすめ

転載: www.cnblogs.com/Scorpicat/p/12067824.html