java 实现 仿QQ聊天系统 简易地实现 网络 在线聊天 代码详解(附源代码)

首先,实现的效果如下图:

java 实现 仿QQ聊天系统 简易地实现 网络 在线聊天 代码详解(附源代码)_第1张图片java 实现 仿QQ聊天系统 简易地实现 网络 在线聊天 代码详解(附源代码)_第2张图片

  这是一个非常经典的例题,几乎在每本程序语言入门书中都会涉及到一部分原理的讲解。我在这里简单地介绍一下代码的实现,让刚学习网络编程的读者更好的理解和实现,二来加深自己的记忆。

  这个原理无非就是 利用服务器端处理消息再返回给客户端,实现客户端之间的信息交互。 这个原理与生活息息相关,比如两部手机之间的电话交流并不是两部机器直接交流,而是通过信息发射台或者卫星来实现信息交互。虽然原理非常简单,但如果想很完整地实现这个功能并不十分容易(至少对我来讲)。

整个程序代码很简短,主要用到的 java Socket套接字、多线程知识。主要难度在于非常容易产生Exception。

下面附上服务器端代码

package chat;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;


public class ChatServer {
	public  static ServerSocket serverForClient=null;
	public static boolean bool1=false;//用来判断是否连接成功
	
	List clients=new  LinkedList();
	
	public static void main(String[] args) {
		ChatServer start=new ChatServer();
		start.runing();
		
		
	
	}
	
	
	public  void runing()  {//连接客户端,并启动线程
		 Socket serverSocket=null;//这个名字起得非常不好 和关键字SeverSocket重名了,很容易混淆,建议读者改掉,我这里懒得改了
		 try {
				serverForClient=new ServerSocket(3333);
				 bool1=true;//当服务器连接成功时 为true
				
				
				 
			} catch (IOException e1) {
				System.out.println("端口被占用,请关闭相关占用程序重启服务器!");
			}
		    try {   int count=0;
						while(bool1) {
							
							if(count==0) {
							System.out.println("*********正在等待客户端连接******");}
							
							count++;
							serverSocket =serverForClient.accept();
						System.out.println("**第"+count+"个客户端正在连接中……");
						Client cc=new Client(serverSocket);
						cc.setClient(cc);
						new Thread(cc).start();
						
						clients.add(cc);
						
						//new Thread(new Client(serverSocket)).start();
					}
						} catch (IOException e1) {
						e1.printStackTrace();
					}finally {
						try {
							serverSocket.close();
							
						} catch (IOException e) {	
						e.printStackTrace();
						}
					}

					
	}
		
class Client implements Runnable{// 启用线程类来 接受客户端
	Client me=null;
    		DataInputStream serverIn=null;
			  DataOutputStream serverOut=null;
			  Socket ss=null;
		public  String accept=null;//这里的字符串名字与accept()方法重名,容易混淆,建议改掉!
		
		public Client(Socket s ){
			  ss=s;
			  try {
				serverIn=new DataInputStream(ss.getInputStream());
			serverOut=new DataOutputStream(ss.getOutputStream());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}


public void send(String sss)	{
	try {
		serverOut.writeUTF(sss);	
	} catch (IOException e) {
		
		e.printStackTrace();
	}
	
}
public void setClient (Client s) {
	me=s;
	
}
public void run() {
	
	try {	
		while(bool1) {//服务器端等待接受客户端的消息
			
			accept=serverIn.readUTF();
				for(int i=0;i

服务器端:建立一个接受 客服端连接的 ServerSocket,当有客户端连接时,得到对应的Socket,并传入给线程,线程保存每一个接入的客服端并接受客服端消息,然后发送给其他所有的客户端。(这相当于一个QQ群,当客户端接入相同的服务器IP和端口时,客户端之间即可实现群聊)

下面附上客户端代码

package chat;



import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.*;

public class ChatClient extends JFrame implements ActionListener{

	 
	 public static boolean bool1=false;//用来判断是否连接成功
	  JTextField text=new JTextField();
			JTextArea area=new JTextArea();	
			JScrollPane scroll=new JScrollPane(area);
			Socket clientSocket=null;
			DataOutputStream clientOut=null;
			 DataInputStream clientIn=null;
	public static void main(String[] args) {
		 
	new ChatClient().launchJFrame();
	
	
	}	

	public void launchJFrame() {
		this.setBounds(400, 400, 400, 400);
		this.setVisible(true);
 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.add(scroll,BorderLayout.CENTER);
		this.add(text,BorderLayout.SOUTH);
		text.addActionListener(this);
		connect();
		
	}

	public void connect() {
		try {
			 clientSocket=new Socket("localhost",3333);
			 bool1=true;
			 clientIn=new DataInputStream(clientSocket.getInputStream());
			clientOut=new DataOutputStream(clientSocket.getOutputStream());
			System.out.println("连接服务器成功");
			new Thread(new Receiver()).start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
		
		
		
	}
	public void actionPerformed(ActionEvent arg0) {
		 String s=text.getText().trim();
		// area.setText(s);	
		 
		 try {
			clientOut.writeUTF(""+s);
			
			area.append("我发送的消息:"+s+"\n");
			clientOut.flush();
			text.setText("");	
//clientOut.close();//这里不能关闭否则没法继续向服务器端发送信息
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
	}
 class Receiver implements Runnable{//内部的类中添加线程:接受服务器消息

		
		public void run() {
			 while(bool1) {
				 try {
				String clientAccept=clientIn.readUTF();
					area.append("接收到的消息:"+clientAccept);
				} catch (IOException e) {
					try {
						if(clientIn!=null)  clientIn.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}
		}
    }
 }

客户端:客户端是一个JFrame 窗口,给文本框添加一个ActionListener监视器,将文本框内容输入到输出流中。和服务器端一样创建内部的线程,让线程去获取服务器发送到输出流中的信息并显示在文本区内。

那么客户端和服务器端写好这个程序就基本完成了,先让服务器端运行起来,之后就可以运行多个客户端。客户端将信息发送到服务器,服务器接受并把它发送到其他客户端,即可实现客户端的在线聊天。

到这里来说 功能已经实现了。但是可以预见,即使我试图使用多个catch尽可能地去抓程序中的异常,并使用finally尽量去关闭已经打开且无用的流。我的代码依然有一些问题。

 

java 实现 仿QQ聊天系统 简易地实现 网络 在线聊天 代码详解(附源代码)_第3张图片

 

当我关闭一个客户端的时候,服务器端会抛出SocketException异常,虽然这并不影响程序的继续运行。这个问题检查代码用点时间应该也容易解决,不过我已经失去耐心,不想再去花时间处理这种异常问题,读者如果使用我的代码可以在此基础上修改。

 

 

 

你可能感兴趣的:(java 实现 仿QQ聊天系统 简易地实现 网络 在线聊天 代码详解(附源代码))