java学习编程练习(局域网多人聊天功能的实现)

此题综合了,最近两周学习的IO流、进程、网络传输等知识,基本实现了多人聊天的功能。经过修改封装,有较好的可读性。

设计思路:

1、建立一个进程类Monitor,其成员变量包括Socket的引用、读和写的引用、客户端的编号名字。为每一个客户端建立Monitor的对象并将其放在静态ArrayList中;

2、通过对ArrayList的枚举实现信息的群发和转发;

3、通过匿名类不类分别建立读和写的进程,并以temp2为开关;

4、在主方法中开启进程clossAll(),并通过枚举ArrayList监控对象的开关temp2。当temp2=false时,关闭当前对象的所有通道、进程,同时从ArrayList上删除;

5、服务器有较好的通用性,只需要客户端具有read和write的能力变可以实现通讯;

6、关于乱码,当编码完全采用GBK编码时,可以解决键盘输入乱码的问题。客户端编码必须同服务器编码保持一致。

类Monitor:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

public class Monitor extends Thread {
	/** 用于存放Socket连接的对象所在的Monitor */
	static ArrayList<Monitor> list = new ArrayList<Monitor>();
	/** 避免nums重复的计数器 */
	static int cout = 0;
	/** 服务器全局输入对象 */
	static Scanner line = new Scanner(System.in);
	/** 端口编号,用cout进行赋值便于确定对象 */
	int nums;
	Socket socket;
	BufferedReader read;
	PrintWriter write;
	String name;
	boolean temp2 = true;

	/**
	 * 构造方法
	 */
	public Monitor(Socket socket) {
		this.socket = socket;
		cout++;
		nums = cout;
		try {
			read = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			write = new PrintWriter(socket.getOutputStream());
		} catch (IOException e) {
			System.out.println(nums + "端口错误!");
		}
		this.start();
	}

	/**
	 * 开启通道进程
	 */
	public void run() {
		names();
		reads();
		writes();
	}

	/**
	 *转发连接用户的信息,实现信息同步
	 */
	void sendMessage(String str) {
		for (int i = 0; i < list.size(); i++) {
			if (nums != list.get(i).nums) {
				list.get(i).write.println(str);
				list.get(i).write.flush();
			}
		}
	}

	/**
	 * 服务台发送信息
	 */
	static void sendTo(String str) {
		if (str != null) {
			str = "帅的飞起说:" + str;
			for (int i = 0; i < list.size(); i++) {
				list.get(i).write.println(str);
				list.get(i).write.flush();
			}
		}
	}

	/**
	 * 读取客户端名字
	 */
	void names() {
		write.println("请输入您的名字!");
		write.flush();
		boolean temp3 = true;
		while (temp3) {
			try {
				Thread.sleep(100);
				String str2 = read.readLine();
				if (str2 != null) {
					name = str2;
					temp3 = false;
					String str4 = "欢迎" + name + "加入聊天室";
					System.out.println(str4);
					sendTo(str4);
				}
			} catch (IOException e) {
				System.out.println("录入客户端名字出错");
				temp2 = false;
				temp3 = false;
			} catch (InterruptedException e) {
				System.out.println("录入客户端名字出错");
				temp2 = false;
				temp3 = false;
			}
		}
	}

	/**
	 * 进程,读取信息并且将信息群发给在线其他人
	 */
	void reads() {
		new Thread(new Runnable() {
			public void run() {
				while (temp2) {
					try {
						sleep(100);
						String str = name + "说:" + read.readLine();
						if (!str.equals(name + "说:")) {
							System.out.println(str);
							sendMessage(str);
						}
					} catch (IOException e) {
						System.out.println(name + "读取错误");
						temp2 = false;
					} catch (InterruptedException e1) {
						System.out.println(name + "read读入异常");
						temp2 = false;
					}
				}
			}
		}).start();
	}

	/**
	 * 进程,群发信息
	 */
	void writes() {
		new Thread(new Runnable() {
			public void run() {
				while (temp2) {
					String str1 = null;
					try {
						str1 = line.nextLine();
					} catch (Exception e) {
					}
					sendTo(str1);
				}
			}
		}).start();
	}

	/**
	 * 关闭当前对象所有进程:当temp2为false时关闭各种进程
	 */
	static void closeAll() {
		new Thread(new Runnable() {
			public void run() {
				boolean temp = true;
				while (temp) {
					int i = 0;
					try {
						sleep(100);
						for (; i < list.size(); i++) {
							if (list.get(i).temp2 == false) {
								if (list.get(i).read != null) {
									list.get(i).read.close();
								}
								if (list.get(i).write != null) {
									list.get(i).write.close();
								}
								if (list.get(i).socket != null) {
									list.get(i).socket.close();
								}
								String str5 = list.get(i).name + "已退出聊天!";
								list.remove(i);
								System.out.println(str5);
								sendTo(str5);
							}
						}
					} catch (IOException e) {
						System.out.println("关闭进程" + list.get(i).nums + "出错");
					} catch (InterruptedException e1) {
						System.out.println("结束程序:等待错误!");
					}
				}
			}
		}).start();
	}
}


主方法:

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

/**
 * 实现多人聊天功能的服务器,主方法类
 */
public class Server {
	/** 当temp1为false时停止服务器 */
	static boolean temp1 = true;

	public static void main(String[] args) {
		try {
			ServerSocket server = new ServerSocket(7845);
			Monitor.closeAll();//开启监控程序用于删除在list上过期的对象
			while (temp1) {
				Monitor.list.add(new Monitor(server.accept()));//监视等待信号
			}
		} catch (IOException e) {
			System.out.println("端口错误!");
		}
	}
}

一个简易的客户端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class SerCient {
	public static void main(String[] args) {
		try {
			Scanner str = new Scanner(System.in);
			Socket socket = new Socket("localhost", 7845);
			final BufferedReader read = new BufferedReader(
					new InputStreamReader(socket.getInputStream()));
			PrintWriter write = new PrintWriter(new OutputStreamWriter(socket
					.getOutputStream()));
			new Thread(new Runnable() {
				public void run() {
					while (true) {
						try {
							Thread.sleep(100);
							String str2 = read.readLine();
							if (str2 != null) {
								System.out.println( str2);
							}

						} catch (IOException e) {
							e.printStackTrace();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}).start();
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			String str3 = str.next();
			while (!str3.equals("88")) {
				write.println(str3);
				write.flush();
				str3 = str.next();
			}
			read.close();
			write.close();
			str.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值