久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

Java用局域網實現聊天室功能

這篇文章主要為大家詳細介紹了Java用局域網實現聊天室功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Java用局域網實現聊天室的具體代碼,供大家參考,具體內容如下

類和接口

Server類(服務器端)

package Test;

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
? ? private static final int SERVER_PORT=30000;
? ? //使用CrazyitMap對象來保存每個客戶名字和對應輸出流之間的對應關系
? ? public static CrazyitMap<String,PrintStream> clients=new CrazyitMap<>();
? ? public void init(){
? ? ? ? try( //建立監聽的ServerSocket
? ? ? ? ? ? ?ServerSocket ss=new ServerSocket(SERVER_PORT))
? ? ? ? {
? ? ? ? ? ? //采用死循環來不斷地接收來自客戶端的請求
? ? ? ? ? ? while(true){
? ? ? ? ? ? ? ? Socket socket=ss.accept();
? ? ? ? ? ? ? ? new ServerThread(socket).start();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //如果拋出異常
? ? ? ? catch (IOException ex){
? ? ? ? ? ? System.out.println("服務器啟動失敗,是否端口"+SERVER_PORT+"已被占用");
? ? ? ? }
? ? }
? ? public static void main(String[] args){
? ? ? ? Server server=new Server();
? ? ? ? server.init();
? ? }
}

ServerThread類

package Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class ServerThread extends Thread {
? ? private Socket socket;
? ? BufferedReader br = null;
? ? PrintStream ps = null;

? ? //定義一個構造器,用于接收一個Socket來創建ServerThread線程
? ? public ServerThread(Socket socket) {
? ? ? ? this.socket = socket;
? ? }

? ? public void run() {
? ? ? ? try {
? ? ? ? ? ? //獲取該Socket對應的輸入流
? ? ? ? ? ? br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
? ? ? ? ? ? //獲取該Socket對應的輸出流
? ? ? ? ? ? ps = new PrintStream(socket.getOutputStream());
? ? ? ? ? ? String line = null;
? ? ? ? ? ? while ((line = br.readLine()) != null) {
? ? ? ? ? ? ? ? //如果讀到的行以CrazyitProtocol.USER_ROUND開始,并以其結束
? ? ? ? ? ? ? ? //則可以確定讀到的是用戶登錄的用戶名
? ? ? ? ? ? ? ? if (line.startsWith(CrazyitProtocol.USER_ROUND) && line.endsWith(CrazyitProtocol.USER_ROUND)) {
? ? ? ? ? ? ? ? ? ? //得到真實消息
? ? ? ? ? ? ? ? ? ? String userName = getRealMsg(line);
? ? ? ? ? ? ? ? ? ? //如果用戶名重復
? ? ? ? ? ? ? ? ? ? if (Server.clients.map.containsKey(userName)) {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("重復");
? ? ? ? ? ? ? ? ? ? ? ? ps.println(CrazyitProtocol.NAME_REP);
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("成功");
? ? ? ? ? ? ? ? ? ? ? ? ps.println(CrazyitProtocol.LOGIN_SUCCESS);
? ? ? ? ? ? ? ? ? ? ? ? Server.clients.put(userName, ps);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //如果讀到的行以CrazyitProtocol.PRIVATE_ROUND開始,
? ? ? ? ? ? ? ? //則可以確定是私聊信息,私聊信息只向特定的輸入流發送
? ? ? ? ? ? ? ? else if (line.startsWith(CrazyitProtocol.PRIVATE_ROUND) && line.endsWith(CrazyitProtocol.PRIVATE_ROUND)) {
? ? ? ? ? ? ? ? ? ? //得到真實的消息
? ? ? ? ? ? ? ? ? ? String userAndMsg = getRealMsg(line);
? ? ? ? ? ? ? ? ? ? //以SPLIT_SIGN分割字符串,前半是私聊用戶,后半是聊天信息
? ? ? ? ? ? ? ? ? ? String user = userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[0];
? ? ? ? ? ? ? ? ? ? String msg = userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[1];
? ? ? ? ? ? ? ? ? ? //獲取私聊用戶對應的輸出流,并發送私聊信息
? ? ? ? ? ? ? ? ? ? Server.clients.map.get(user).println(Server.clients.getKeyByValue(ps) + "悄悄對你說:" + msg);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //公聊要向每一個Socket發送
? ? ? ? ? ? ? ? else {
? ? ? ? ? ? ? ? ? ? //得到真實消息
? ? ? ? ? ? ? ? ? ? String msg = getRealMsg(line);
? ? ? ? ? ? ? ? ? ? //遍歷clients中的每個輸出流
? ? ? ? ? ? ? ? ? ? for (PrintStream clientPs : Server.clients.valueSet()) {
? ? ? ? ? ? ? ? ? ? ? ? clientPs.println(Server.clients.getKeyByValue(ps) + "說:" + msg);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //捕獲到異常后,表明Socket對應的客戶端已經出現了問題
? ? ? ? //所以程序將其對應的輸出流從Map中刪除
? ? ? ? catch (IOException e) {
? ? ? ? ? ? Server.clients.removeByValue(ps);
? ? ? ? ? ? System.out.println(Server.clients.map.size());
? ? ? ? ? ? //關閉網絡,IO資源
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (br != null) {
? ? ? ? ? ? ? ? ? ? br.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (ps != null) {
? ? ? ? ? ? ? ? ? ? ps.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (socket != null) {
? ? ? ? ? ? ? ? ? ? socket.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (IOException ex) {
? ? ? ? ? ? ? ? ex.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? //將讀到的內容去掉前后協議字符,恢復成真實數據
? ? private String getRealMsg(String line) {
? ? ? ? return line.substring(CrazyitProtocol.PROTOCOL_LEN,line.length()-CrazyitProtocol.PROTOCOL_LEN);
? ? }
}

Client類

package Test;

import javax.swing.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
? ? private static final int SERVER_PORT=30000;
? ? private Socket socket;
? ? private PrintStream ps;
? ? private BufferedReader brServer;
? ? private BufferedReader keyIn;
? ? public void init(){
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? //初始化代表鍵盤的輸入流
? ? ? ? ? ? keyIn=new BufferedReader(new InputStreamReader(System.in));
? ? ? ? ? ? //連接到服務器端
? ? ? ? ? ? socket=new Socket("127.0.0.1",SERVER_PORT);
? ? ? ? ? ? //獲取該Socket對應的輸入流和輸出流
? ? ? ? ? ? ps=new PrintStream(socket.getOutputStream());
? ? ? ? ? ? brServer=new BufferedReader(new InputStreamReader(socket.getInputStream()));
? ? ? ? ? ? String tip=" ";
? ? ? ? ? ? //采用不斷循環地彈出對話框要求輸入用戶名
? ? ? ? ? ? while(true){
? ? ? ? ? ? ? ? String userName= JOptionPane.showInputDialog(tip+"輸入用戶名");
? ? ? ? ? ? ? ? //用戶輸入的用戶名前后增加協議字符串后發送
? ? ? ? ? ? ? ? ps.println(CrazyitProtocol.USER_ROUND+userName+CrazyitProtocol.USER_ROUND);
? ? ? ? ? ? ? ? //讀取服務器端的響應
? ? ? ? ? ? ? ? String result=brServer.readLine();
? ? ? ? ? ? ? ? //如果用戶名重復,則開始下一次循環
? ? ? ? ? ? ? ? if (result.equals(CrazyitProtocol.NAME_REP)){
? ? ? ? ? ? ? ? ? ? tip="用戶名重復,請重試";
? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? //服務器端登錄成功
? ? ? ? ? ? ? ? if (result.equals(CrazyitProtocol.LOGIN_SUCCESS)){
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //捕獲到異常,關閉網絡資源,并退出該程序
? ? ? ? catch (UnknownHostException ex){
? ? ? ? ? ? System.out.println("找不到遠程服務器,請確定服務器已經啟動");
? ? ? ? ? ? closeRs();
? ? ? ? ? ? System.exit(1);
? ? ? ? }
? ? ? ? catch(IOException ex){
? ? ? ? ? ? System.out.println("網絡異常,請重新登錄");
? ? ? ? ? ? closeRs();
? ? ? ? ? ? System.exit(1);
? ? ? ? }
? ? ? ? //以該Socket對應的輸入流啟動ClientThread線程
? ? ? ? new ClientThread(brServer).start();
? ? }
? ? //定義一個讀取鍵盤輸出,并以網絡發送的方法
? ? private void readAndSend(){
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? //不斷讀取鍵盤輸入
? ? ? ? ? ? String line=null;
? ? ? ? ? ? while ((line=keyIn.readLine())!=null){
? ? ? ? ? ? ? ? //如果發送的信號中有冒號,并以//開頭,則認為想發送私聊信息
? ? ? ? ? ? ? ? if (line.indexOf(":")>0&&line.startsWith("http://")){
? ? ? ? ? ? ? ? ? ? line=line.substring(2);
? ? ? ? ? ? ? ? ? ? ps.println(CrazyitProtocol.PRIVATE_ROUND+line.split(":")[0]+CrazyitProtocol.SPLIT_SIGN+line.split(":")[1]+CrazyitProtocol.PRIVATE_ROUND);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ps.println(CrazyitProtocol.MSG_ROUND+line+CrazyitProtocol.MSG_ROUND);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? catch (IOException ex){
? ? ? ? ? ? System.out.println("網絡通信異常!請重新登錄");
? ? ? ? ? ? closeRs();
? ? ? ? ? ? System.exit(1);
? ? ? ? }
? ? }
? ? //關閉Socket,輸入流,輸出流的方法
? ? private void closeRs(){
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? if (keyIn!=null){
? ? ? ? ? ? ? ? ps.close();
? ? ? ? ? ? }
? ? ? ? ? ? if (brServer!=null){
? ? ? ? ? ? ? ? ps.close();
? ? ? ? ? ? }
? ? ? ? ? ? if (ps!=null){
? ? ? ? ? ? ? ? ps.close();
? ? ? ? ? ? }
? ? ? ? ? ? if (socket!=null){
? ? ? ? ? ? ? ? keyIn.close();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? catch (IOException ex){
? ? ? ? ? ? ex.printStackTrace();
? ? ? ? }
? ? }

? ? public static void main(String[] args){
? ? ? ? Client client=new Client();
? ? ? ? client.init();
? ? ? ? client.readAndSend();
? ? }
}

ClientThread類

package Test;

import java.io.BufferedReader;
import java.io.IOException;

public class ClientThread extends Thread {
? ? //該客戶端線程負責處理輸入流
? ? BufferedReader br=null;
? ? //使用一個網絡輸入流來創建客戶端線程
? ? public ClientThread(BufferedReader br){
? ? ? ? this.br=br;
? ? }
? ? public void run(){
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? String line=null;
? ? ? ? ? ? //不斷地從輸入流中讀取數據,并將這些數據打印輸出
? ? ? ? ? ? while((line=br.readLine())!=null){
? ? ? ? ? ? ? ? System.out.println(line);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? catch (IOException ex){
? ? ? ? ? ? ex.printStackTrace();
? ? ? ? }
? ? ? ? finally {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (br!=null){
? ? ? ? ? ? ? ? ? ? br.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (IOException ex){
? ? ? ? ? ? ? ? ex.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
}

CrazyitMap類

package Test;

import java.util.*;

public class CrazyitMap<k,v> {
? ? //創建一個線程安全的HashMap
? ? public Map<k,v> map= Collections.synchronizedMap(new HashMap<k,v>());
? ? //根據value來刪除指定項
? ? public synchronized void removeByValue(Object value){
? ? ? ? for (Object key:map.keySet()){
? ? ? ? ? ? if (map.get(key)==value){
? ? ? ? ? ? ? ? map.remove(key);
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? //獲取所有value組成的Set集合
? ? public synchronized Set<v> valueSet(){
? ? ? ? Set<v> result=new HashSet<v>();
? ? ? ? //將map中的所有value添加到result集合中
? ? ? ? map.forEach((key,value)->result.add(value));
? ? ? ? return result;
? ? }
? ? //根據value查找key
? ? public synchronized k getKeyByValue(v value){
? ? ? ? //遍歷所有key組成的集合
? ? ? ? for (k key:map.keySet()){
? ? ? ? ? ? //如果指定key對應的value與被搜索的value相同,則返回對應的key
? ? ? ? ? ? if(map.get(key)==value||map.get(key).equals(value)){
? ? ? ? ? ? ? ? return key;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return null;
? ? }
? ? //實現put()方法,該方法不允許value重復
? ? public synchronized v put(k key,v value){
? ? ? ? //遍歷所有value組成的集合
? ? ? ? for (v val:valueSet()){
? ? ? ? ? ? //如果某個value與試圖放入集合的value相同
? ? ? ? ? ? //則拋出一個RuntimeException異常
? ? ? ? ? ? if (val.equals(value)&&val.hashCode()==value.hashCode()){
? ? ? ? ? ? ? ? throw new RuntimeException("MyMap實例不允許有重復的value");
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return map.put(key,value);
? ? }
}

CrazyitProtocol類

package Test;

public interface CrazyitProtocol {
? ? //定義協議字符串的長度
? ? int PROTOCOL_LEN=2;
? ? //下面是一些協議字符串,服務器端和客戶端交換的信息都應該在前后添加這種特殊字符串
? ? String MSG_ROUND="ηθ";
? ? String USER_ROUND="∏∑";
? ? String LOGIN_SUCCESS="1";
? ? String NAME_REP="-1";
? ? String PRIVATE_ROUND="★【";
? ? String SPLIT_SIGN="卐";
}

運行結果:

打開服務器并且運行三個客戶端用戶名分別是xuwei,jiji和yaou

首先發送一句公開信息:
xuwei發送了一句話

jiji收到:

yaou收到:

再發送一句私聊信息給jiji
xuwei發送了一句悄悄話:

jiji收到:

yaou沒有收到:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持html5模板網。

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

堆(優先隊列)是一種典型的數據結構,其形狀是一棵完全二叉樹,一般用于求解topk問題。本文將利用Java語言實現堆,感興趣的可以學習一下
Dijkstra(迪杰斯特拉)算法是典型的單源最短路徑算法,用于計算一個節點到其他所有節點的最短路徑。本文將詳解該算法的圖解與實現,需要的可以參考一下
這篇文章主要介紹了Java中ThreadLocal導致內存OOM的原因分析,文章基于Java的相關內容展開ThreadLocal導致內存OOM的原因分析,需要的小伙v阿布可以參考一下
這篇文章主要介紹了Java中CyclicBarrier?循環屏障,可以實現讓一組線程等待至某個狀態屏障點之后再全部同時執行,下面文章分享CyclicBarrier循環屏障的原理,需要的小伙伴可以參考一下
這篇文章主要介紹了利用Java代碼寫一個并行調用模板,文章基于Java的相關內容展開寫一個并行調用模板的詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下
API(Application?Programming?Interface)應用程序編程接口,java?API是一本程序員字典,是JDK提供給我們使用的類的說明文檔,下面這篇文章主要給大家介紹了關于Java高版本Api在Android中的使用方法,需
主站蜘蛛池模板: 成人激情免费视频 | 欧美午夜一区二区三区免费大片 | 久久aⅴ乱码一区二区三区 亚洲欧美综合精品另类天天更新 | 视频在线一区二区 | 精品一区二区三区av | 成人日批视频 | 九九免费 | 欧美精品91| 国产精品一区三区 | 色综合久 | 色视频在线播放 | 国产在线看片 | 午夜国产精品视频 | 日韩中文字幕在线观看 | 精品美女在线观看 | 一区二区在线免费观看 | 在线免费观看视频黄 | 成人在线免费网站 | 国产成人精品一区 | 天天弄天天操 | 99免费在线观看视频 | 欧美日韩久久精品 | 美女逼网站| 成人三级电影 | 日本一二区视频 | 91一区| 成人精品一区二区三区中文字幕 | 欧美国产精品久久久 | 亚洲一区二区三区免费在线 | 国产精品乱码一二三区的特点 | 国产亚洲人成a在线v网站 | 中文字幕日韩欧美一区二区三区 | 一区二区三区亚洲 | 福利片在线观看 | 中文字幕亚洲欧美日韩在线不卡 | 亚洲国产欧美91 | 看毛片网站 | 亚洲精品在线播放 | 欧美精品一区二区三区在线播放 | 一区二区三区国产 | 国产精品美女视频 |