基于Java的群聊系统

最近研究生复试,特定将自己大二写的程序拿出来,因为实在没什么项目经验。当时也是在网上参考了些信息,不过自己也忘记是哪个博主的了,特此感谢之前的博主。接下来将这个程序的思路与源码分享给大家。里面有多多不足还请包涵。
完整的程序代码我将放在我的GitHub上,供大家下载。
GitHub完整源码

首先是服务器部分:
首先写一个服务器类继承JFrame用于可视化窗口。在类里面写以获得消息的函数getMessage。在getMessage里面启动信息传输线程。创建套接字不断接受来客户端的套接字。将新增加的客户端增加到列表中。代表如下:

public void getmessages()
	{	//启动普通信息传输器
		new PrintOutThread();
		try {
			ServerSocket server=null;
			server=new ServerSocket(2559);
			System.out.println("普通消息传输服务器"+2559);
			String messages;
			int i=0;
			Socket s;
			while(true)
			{
				s=server.accept();
				//receiveFile(s);
				thread_list.add(new ServerThread(s,i));
				i++;
			}
			
		}
		catch(Exception e)
		{
			System.err.println("发生异常:"+e);
			e.printStackTrace();
		}
	}

客户端列表的定义如下:

private static List<ServerThread> thread_list = new ArrayList<ServerThread>();

接下来我们解析ServerThread类。
1,在类中定义int id,Socket socket两个变量。
2,为了接收和发出消息定义一个输入流一个输出流对象
private ObjectOutputStream m_output;//输出流
private ObjectInputStream m_input;//输入流
接下来则在创建构造函数包含套接字socket,id两个参数。
id是用来标准每个客户端的。在构造函数中获取获取套接字的输入输出流。并且启动线程。代码如下:

public ServerThread(Socket s,int i)
		{
			client = s;
			id=i;
			try
			{
				m_input=new ObjectInputStream(s.getInputStream());
				m_output=new ObjectOutputStream(s.getOutputStream());
				start();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}

接着我们查看run()函数里面的动作。
即我们不断获取来自客户端的消息,直到接收到客户端退出的消息。在接收消息时这里是将接收的消息全部放入消息队列当中,因为我们实现的是群聊。从而要实现一个客户端发完消息,服务器要将消息转发给除自己外,其他所有客户端。
代码如下:

public void run() {
			// TODO Auto-generated method stub
			try
			{
				String messages;
				offLine=true;
				while(offLine)
				{
					messages=m_input.readObject().toString();
					if(messages.equals("!exit!"))
						offLine=false;
					message_list.add(new Message(id,messages));
					isPrint=true;
				}
				m_output.flush();
				m_output.close();
				m_input.close();
				client.close();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}

接下来我们就是讲下Message类,其实这个类主要是就是为了将消息绑上ID等等有发送线程发送就知道是谁的消息了。

public class Message {
	private int ID;
	private String msg;
	public Message(int n,String m)
	{
		ID=n;
		msg=m;
	}
	public int getName()
	{
		return ID;
	}
	public String getMsg()
	{
		return msg;
	}		
}

就下来就是服务器的最后一部分了。就是要开始发送消息了。在之前我们就已经启动了消息进程。直接在消息进程的run函数发送数据。首先对消息队列有个判断,若消息队列为空,则阻塞消息队列一段时间,目标为了将cpu让给其他线程。对与这一部分。大家可以去看下操作系统,cpu调度这一块。会给更加便于大家理解。接下来接收将消息队列取出消息。并且在服务器端队列取出各个来客户端的线程。判断若消息不是来自该客户端,若不是,则该服务器线程端发送给数据给该客户端。若是则不发送。代码如下:

public void run() {
		while (true) {
			//如果消息队列没有消息则暂停当前线程,把cpu片段让出给其他线程,提高性能
			if (!isPrint) {
				try {
					Thread.sleep(500);
					sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				continue;
			}
			// 将缓存在队列中的消息按顺序发送到各客户端,并从队列中清除。
			Message msg = (Message)message_list.getFirst();
			// 对所有的用户的线程遍历,如果不是自己发的消息就广播给其他人
			for (int i = 0; i < thread_list.size(); i++) {
				// 由于添加线程和用户是一起的,所以i所对应的用户就是i所对应的线程,可以根据这个判断是不是自己的线程
				ServerThread thread = thread_list.get(i);
					try {
						if(i!=msg.getName())
						thread.sendMessage(msg.getMsg());
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				
			}
			message_list.removeFirst();
			isPrint = message_list.size() > 0 ? true : false;
		}

最后一块大家看代码其实会更加清楚。这就是服务器的部分了。理解好服务器很重要。客户端相对来说就很好理解了。客户端我也上传到GitHub了,大家只需要上去下载就行了。过程就不说了。大家自己看看。

原创文章 6 获赞 4 访问量 906

猜你喜欢

转载自blog.csdn.net/a770198892/article/details/105893207