JavaSE 网络编程 多线程 实现聊天室

等一个大佬告诉我这波服务器资源怎么释放 …

服务器驱动类

package cn.hyo.day9.ChatRoom;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 @author weng
 @build  2020年7月27日 下午2:54:31

 TODO 服务器端
*/

//服务器资源释放难度有点大
public class TriggerServer {	//服务器驱动类
	private static CopyOnWriteArrayList<RDWRChannel> list;
	private static ServerSocket server_socket;
	private static ExecutorService pool;
	public static void main(String[] args) throws Exception {
		init();
		
		while(true) {
			
			Socket client = server_socket.accept();
			RDWRChannel channel = new RDWRChannel(client);
			pool.execute(channel);
			list.add(channel);
			System.out.println("用户:"+channel.name+"连接成功");
			
			channel.SendToClient(channel.name+"进入了聊天室", true);
		}
	}
	private static void init() throws Exception { 
		server_socket =new ServerSocket(9999); 
		list =new CopyOnWriteArrayList<RDWRChannel>();
		pool =Executors.newCachedThreadPool();		//带缓存的线程池
	}
	
	static class RDWRChannel implements Runnable{	//服务器端读写通道
		private Socket socket;
		private DataInputStream receiver;
		private DataOutputStream sender;
		private String name;
		public RDWRChannel(Socket socket) throws Exception {
			super();
			this.socket = socket;
			receiver =new DataInputStream(socket.getInputStream());
			sender =new DataOutputStream(socket.getOutputStream());
			this.name =receiveFromClient();
		}
		private String receiveFromClient() throws Exception {return receiver.readUTF();}
		private void SendToClient(String s ,boolean isSys) throws Exception {
			String[] spl =analysisInfo(s);
			if(!spl[0].equals("")) {	//私信
				for(RDWRChannel channel :list) if(channel.name.equals(spl[0])) {channel.SendToClientOne(this.name+"悄悄地对您说:"+spl[1]);}
			}else {						//群发
				if(isSys) {
					s ="<系统提示>"+spl[1]+"<系统提示>"; 
				}else {
					s =this.name+":"+spl[1];
				}
				for(RDWRChannel channel :list) channel.SendToClientOne(s);
			}
		}
		private void release() throws Exception {QuickRelease.release(socket ,receiver ,sender);}
		private void quit() throws Exception { list.remove(this);System.out.println("用户"+this.name+"连接切断"); SendToClient(this.name+"退出了聊天室", true); Thread.sleep(500); release();}
		private void SendToClientOne(String s) throws Exception {sender.writeUTF(s);}
		private String[] analysisInfo(String s) {
			String[] spl =new String[2]; 
			if(s.startsWith("@")) {
				spl[0] =s.substring(1 ,s.indexOf(":")); 
				spl[1] =s.substring(s.indexOf(":") +1);
				return spl;
			}
			spl[0] ="";
			spl[1] =s;
			return spl;
		}
		@Override
		public void run() {
			while(true) {
				try {
					String s =receiveFromClient();
					if(s.equals("quit")) {SendToClientOne("quit"); break;} else SendToClient(s, false);
				} catch (Exception e) {
					e.printStackTrace();
					try {
						release();
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
			}
			try {
				quit();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

客户端驱动类

package cn.hyo.day9.ChatRoom;

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

/*
 @author weng
 @build  2020年7月27日 下午2:54:47

 TODO 客户端驱动类
*/
public class TriggerClient {
	private static Socket socket;
	private static BufferedReader console;
	public static void main(String[] args) throws Exception {
		init();
		
		System.out.println("<系统提示>请输入您的昵称<系统提示>");
		String uname = console.readLine().trim();
		
		WRChannelClient wrChannelClient = new WRChannelClient(socket.getOutputStream() ,uname);
		RDChannelClient rdChannelClient = new RDChannelClient(socket.getInputStream());
		Thread wrThread = new Thread(wrChannelClient);
		Thread rdThread = new Thread(rdChannelClient);
		wrThread.start();
		rdThread.start();
		
		while(true) if(!rdThread.isAlive()) break;
		release();
		System.out.println("客户端资源释放完成");
	}
	private static void release() throws Exception { QuickRelease.release(console ,socket);}
	private static void init() throws Exception {
		socket = new Socket("localhost" ,9999);
		console = new BufferedReader(new InputStreamReader(System.in));
	}
}

客户端 读通道

package cn.hyo.day9.ChatRoom;
/*
 @author weng
 @build  2020年7月27日 下午3:32:04

 TODO 客户端 读通道
*/

import java.io.DataInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class RDChannelClient implements Runnable{
	private InputStream input_socket;
	private DataInputStream receiver;
	private SimpleDateFormat time;
	public RDChannelClient(InputStream input_socket) throws Exception {
		super();
		this.input_socket = input_socket;
		receiver =new DataInputStream(this.input_socket);
		time =new SimpleDateFormat("MM-dd hh:mm");
	}
	private String receiveFromServer() throws Exception {return receiver.readUTF();}
	void release() throws Exception {System.out.println("尝试关闭读通道"); QuickRelease.release(input_socket ,receiver);}
	@Override
	public void run() {
		while(true) {
			try {
				String s =receiveFromServer();
				if(s.equals("quit")) break; else {System.out.println(time.format(new Date())); System.out.println(s);}
			} catch (Exception e) {
				e.printStackTrace();
				try {
					release();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		}
		try {
			release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

客户端 写通道

package cn.hyo.day9.ChatRoom;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

/*
 @author weng
 @build  2020年7月27日 下午3:32:13

 TODO 客户端 写通道
*/
public class WRChannelClient implements Runnable{
	private OutputStream output_socket;
	private String uname;
	private BufferedReader console;
	private DataOutputStream sender;
	private boolean isRunning =true;
	public boolean getIsRunning() {return isRunning;}
	public WRChannelClient(OutputStream output_socket, String uname) throws Exception {
		super();
		this.uname = uname;
		this.output_socket =output_socket;
		console =new BufferedReader(new InputStreamReader(System.in));
		sender =new DataOutputStream(this.output_socket);
		sendToServer(this.uname);
	}
	String getFromConsole() throws Exception {return console.readLine().trim();}
	void sendToServer(String s) throws Exception {sender.writeUTF(s); sender.flush();}
	void release() throws Exception {System.out.println("尝试关闭写通道"); QuickRelease.release(console ,output_socket ,sender);}
	@Override
	public void run() {
		while(true) {
			try {
				String s =getFromConsole();
				if(!s.equals("")) {
					sendToServer(s);
					if(s.equals("quit")) break;
				}
			} catch (Exception e) {
				e.printStackTrace();
				try {
					release();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		}
		try {
			release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

资源释放类

public class QuickRelease {
	static void release(Closeable ...clo) throws Exception {
		for(Closeable c :clo) if(c !=null) c.close();
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43638238/article/details/107637122