思考
- クライアントは、内部クラスは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(); } } コンテナ。リセット(); //転送後消去 } } }
ショー
実行しているサーバーは、複数のクライアントを実行します。