100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > java 实现 仿QQ聊天系统 简易地实现 网络 聊天 代码详解(附源代码)

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

时间:2019-09-25 10:16:15

相关推荐

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

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

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

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

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

下面附上服务器端代码

package chat;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import .ServerSocket;import .Socket;import java.util.LinkedList;import java.util.List;public class ChatServer {public static ServerSocket serverForClient=null;public static boolean bool1=false;//用来判断是否连接成功List<Client> clients=new LinkedList<Client>();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 blocke.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<clients.size();i++) {//把接受到的消息发送给每一个客户端Client c=clients.get(i);if(me!=c) {c.send(accept+"\n");}}//System.out.println(""+accept); //这句话在代码全部完成前可以用来测试服务器是否收到客户端消息}}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {try {if(ss!=null) ss.close();if(serverIn!=null) serverIn.close();if(serverOut!=null) serverOut.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}

服务器端:建立一个接受 客服端连接的 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 .ServerSocket;import .Socket;import .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 blocke.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 blocke1.printStackTrace();}}}}}}

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

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

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

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。