《Java项目实践》:简单聊天程序

由于这个简单程序,还是涉及到很多的知识点,下面我们就一点一点的来完成。

我们熟悉的QQ聊天,就有一个界面,是吧,我们自己做一个简单的聊天程序,因此我们也就需要为Client写一个界面。因此,这就是我们第一步需要完成的任务。

第一步:为Client端写一个界面

完成一个界面有两种方法,一种是使用Frame对象来完成,另外一种是继承JFrame类来完成.本项目使用第二种。

第二种继承JFrame类完成的界面的程序如下:

    public class ChatClient extends JFrame{private TextField tf=null;private TextArea ta=null;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);tf=new TextField();ta=new TextArea();this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);}}

第一种使用JFrame对象来实现与第二种类似,代码如下:

    public class ChatClient_v1 {private TextField tf =null;private TextArea ta = null;public static void main(String[] args) {new ChatClient_v1().launch();}private void launch() {JFrame frame=new JFrame();frame.setTitle("client端");frame.setLocation(300,400);frame.setSize(300,400);tf = new TextField();ta = new TextArea();frame.add(BorderLayout.SOUTH,tf);frame.add(BorderLayout.NORTH, ta);frame.pack();frame.setVisible(true);}}

运行结果如下:

这样,我们的第一步就算完成了。

在QQ聊天中,当我们在输入消息窗口中输入好消息后,当我们按下回车键后,消息第一会出现在我们窗口的上面,第二会发送个服务器端。

下面我们先完成这两个功能。

2、第二步:为Client端的输入窗口添加回车事件

为TextField添加回车事件有两种方法,具体看这篇博文:http://blog.sina.com.cn/s/blog_908652640100ut12.html

public class ChatClient extends JFrame{private TextField tf=null;private TextArea ta=null;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");}});this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);}}

这样就完成了为TextField添加回车事件。

为了和QQ聊天更加贴近,我们还对其显示在TextArea中进行了一些细节的处理(例如,TextArea中的内容为原先的内容经过换行后添加新的内容等)。本想和QQ一样,Client端发送的内容显示在TextArea的右边,但是没有找到相应的方法。

下面进行下一步的实现,将内容发送到Server端。

但是,将Client端的内容发送的Server端,有如下的几个小的步骤需要实现,例如,Client端和Server端先需要建立连接,然后才能通信,是吧。因此,我们想完成建立连接的过程。

第三步:Client端和Server端建立连接

首先先创建一个Server类,代码如下:

    public class ChatServer {private ServerSocket server=null;public static void main(String[] args) {new ChatServer().start();}private void start(){boolean b_serverStart = false;try {//监听本地地址且端口号为8888server = new ServerSocket(8888);b_serverStart = true;} catch (IOException e) {e.printStackTrace();}while(b_serverStart){//等待客户端的连接Socket client = null;try {client = server.accept();} catch (IOException e) {e.printStackTrace();}  System.out.println("与客户端连接成功!");  }}}

而Client端主要添加了一个connect方法

    private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);client.setSoTimeout(10000);  } catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}

Client端完整代码如下:

    public class ChatClient extends JFrame{private TextField tf = null;private TextArea ta = null;private Socket client =null;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");}});this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);connect();}private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);client.setSoTimeout(10000);  } catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}

这样就建立了一个Server端和Client的连接。

当Server端启动成功后,支持任意多个Client端来建立连接。

以上就是Server端和Client端建立连接,接下来需要完成的任务就是Client端给Server端发送数据

第四步:Client端给Server端发送数据

在Client端,主要是在TextField的的Listener中的代码上面添加一些代码,代码如下:

    private class ClientListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");//往服务器端发送数据 try {bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));} catch (IOException e) {e.printStackTrace();}try {bw.write(content);bw.flush();} catch (IOException e) {e.printStackTrace();}try {bw.close();client.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

Client端完整代码如下:

    public class ChatClient extends JFrame{private TextField tf = null;private TextArea ta = null;private Socket client =null;private BufferedWriter bw = null;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ClientLisenter());this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);connect();}private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);client.setSoTimeout(10000);  } catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private class ClientLisenter implements ActionListener{@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");try {bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));} catch (IOException e) {e.printStackTrace();}try {bw.write(content);bw.flush();} catch (IOException e) {e.printStackTrace();}try {bw.close();client.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

而在Server端的代码如下,代码思想为:Server端每接收一个Client的连接请求,就开启一个线程来进行数据的接收处理。

    public class ChatServer {private ServerSocket server = null;public static void main(String[] args) {new ChatServer().start();}private void start(){boolean b_serverStart = false;try {//监听本地地址且端口号为8888server = new ServerSocket(8888);b_serverStart = true;} catch (IOException e) {//解决打开多个Server端的情况System.out.println("请关闭已经打开的Server端,重新开启");System.exit(0);}while(b_serverStart){//等待客户端的连接,如果没有获取连接  Socket client = null;try {client = server.accept();} catch (IOException e) {e.printStackTrace();}  System.out.println("与客户端连接成功!");  //为每个客户端连接开启一个线程  new Thread(new ServerThread(client)).start();  }try {server.close();} catch (IOException e) {e.printStackTrace();}}private class ServerThread implements Runnable{private Socket client = null;private DataInputStream dis = null;private boolean b_connect = false;public  ServerThread(Socket client) {this.client=client;try {dis = new DataInputStream(this.client.getInputStream());b_connect=true;} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() { try{while(b_connect){  //接收从客户端发送过来的数据  String str= dis.readUTF();if(str == null || "".equals(str)){  b_connect = false;  }else{  if("bye".equals(str)){  b_connect = false;  }else{  //将接收到的字符串前面加上输出到控制台System.out.println(str);}  }  }}catch(IOException e){System.out.println("client端关闭了");//e.printStackTrace();}finally{try{if(dis!=null) dis.close();if(client!=null) client.close();}catch(IOException e){e.printStackTrace();}               }}           }}

但是,里面有一个bug,Server端只能接收Client端的发送的第一条语句,但发送第二条语句时,就报如下的错误:

    java.net.SocketException: Socket is closedat java.net.Socket.getOutputStream(Unknown Source)at client.ChatClient$ClientLienter.actionPerformed(ChatClient.java:92)at java.awt.TextField.processActionEvent(Unknown Source)at java.awt.TextField.processEvent(Unknown Source)at java.awt.Component.dispatchEventImpl(Unknown Source)at java.awt.Component.dispatchEvent(Unknown Source)at java.awt.EventQueue.dispatchEventImpl(Unknown Source)at java.awt.EventQueue.access$500(Unknown Source)at java.awt.EventQueue$3.run(Unknown Source)at java.awt.EventQueue$3.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)at java.awt.EventQueue$4.run(Unknown Source)at java.awt.EventQueue$4.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)at java.awt.EventQueue.dispatchEvent(Unknown Source)at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)at java.awt.EventDispatchThread.pumpEvents(Unknown Source)at java.awt.EventDispatchThread.pumpEvents(Unknown Source)at java.awt.EventDispatchThread.run(Unknown Source)java.io.IOException: Stream closedat java.io.BufferedWriter.ensureOpen(Unknown Source)at java.io.BufferedWriter.write(Unknown Source)at java.io.Writer.write(Unknown Source)at client.ChatClient$ClientLienter.actionPerformed(ChatClient.java:98)

即java.net.SocketException: Socket is closed 和java.io.IOException: Stream closed。

因此,将ChatClient端最后的代码注释掉就OK了。

                try {br.close();client.close();  } catch (IOException e) {e.printStackTrace();} 

现在又出现了新的问题,当我们输入多条消息时,Server端不读取消息,而是等数据达到一定长度或者是Client关闭后,才读取消息。

将BufferedReader/BufferedWrite换成 DataInputStream/DataOutputStream就可以了。

完整代码如下:

    public class ChatClient extends JFrame{private TextField tf = null;private TextArea ta = null;private Socket client =null;private DataOutputStream  dos = null;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){disconnect();System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ClientLisenter());this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);connect();}private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);client.setSoTimeout(10000); dos = new DataOutputStream(client.getOutputStream());} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void disconnect(){  try {if(dos!=null) dos.close();if(client!=null) client.close();} catch (IOException e) {e.printStackTrace();}}private class ClientLisenter implements ActionListener{@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");try {dos.writeUTF(content);dos.flush();} catch (IOException e) {e.printStackTrace();}}}}

以上就是Client端发送数据到Server端的代码实现。

最后来实现下Server端发送数据到Client端。

第五步:Server端发送数据到Client端

有了上面的基础,Server端发送数据到Client端就比较好实现了

Client端的代码主要是在上一个版本的基础上添加了一个receiver 函数,这个函数使用了一个while循环来做。

    public class ChatClient extends JFrame{private TextField tf = null;private TextArea ta = null;private Socket client =null;private DataOutputStream  dos = null;private DataInputStream dis = null;private boolean b_conn =false;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){disconnect();System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ClientLisenter());this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);connect();receiver();}private void receiver() {while(b_conn){String str = null;try {//从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常  str = dis.readUTF();} catch (IOException e) {System.out.println("Time out, No response"); }System.out.println(str);}}private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);client.setSoTimeout(10000); dos = new DataOutputStream(client.getOutputStream());dis = new DataInputStream(this.client.getInputStream());b_conn = true;} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void disconnect(){  try {b_conn = false;if(dos!=null) dos.close();if(client!=null) client.close();} catch (IOException e) {e.printStackTrace();}}private class ClientLisenter implements ActionListener{@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* */if(ta.getText().trim().length()!=0){ta.setText(ta.getText()+"\n"+content);}else{ta.setText(content);}tf.setText("");try {dos.writeUTF(content);dos.flush();} catch (IOException e) {e.printStackTrace();}}}}   

Server端的代码如下:

    public class ChatServer {private ServerSocket server = null;public static void main(String[] args) {new ChatServer().start();}private void start(){boolean b_serverStart = false;try {//监听本地地址且端口号为8888server = new ServerSocket(8888);b_serverStart = true;} catch (IOException e) {//解决打开多个Server端的情况System.out.println("请关闭已经打开的Server端,重新开启");System.exit(0);}while(b_serverStart){//等待客户端的连接,如果没有获取连接  Socket client = null;try {client = server.accept();} catch (IOException e) {e.printStackTrace();}  System.out.println("与客户端连接成功!");  //为每个客户端连接开启一个线程  new Thread(new ServerThread(client)).start();  }try {server.close();} catch (IOException e) {e.printStackTrace();}}private class ServerThread implements Runnable{private Socket client = null;private DataInputStream dis = null;private DataOutputStream dos = null;private boolean b_connect = false;public  ServerThread(Socket client) {this.client=client;try {dis = new DataInputStream(this.client.getInputStream());dos = new DataOutputStream(client.getOutputStream()); b_connect=true;} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() { try{while(b_connect){  //接收从客户端发送过来的数据  String str= dis.readUTF();if(str == null || "".equals(str)){  b_connect = false;  }else{  if("bye".equals(str)){  b_connect = false;  }else{  //将接收到的字符串前面加上输出到控制台System.out.println(str);//将Client端发送过来的数据+时间发送回去dos.writeUTF("server在时间"+new Date().toString()+"收到信息:"+str);}  }  }}catch(IOException e){System.out.println("client端关闭了");//e.printStackTrace();}finally{try{if(dis!=null) dis.close();if(dos!=null) dos.close();if(client!=null) client.close();}catch(IOException e){e.printStackTrace();}               }}           }}

以上就实现了简单Client端和Server端的通信。

最后一步:Server端实现消息的转发

前一个版本实现了Server端和Client的通信,但是,离我们的聊天程序还差一点点。

QQ聊天的流程时这样,

因此,在Server端,还需要将Client端发送来的数据转发给其它的客户端。

在Server端,

1、首先需要将连接此服务器端的所有Client端记录下来。

2、然后,如果有Client发送消息,则将消息广播出去。

有一个细节需要注意:如果某个Client端关闭了,则在Server端保存有所有Client端记录的结果中需要将此Client端的记录移出。

实现的代码如下:

    public class ChatServer {private ServerSocket server = null;//记录所有连接上此服务器的客户端private List<ServerThread> serverThreads = new ArrayList<ServerThread>();public static void main(String[] args) {new ChatServer().start();}private void start(){boolean b_serverStart = false;try {//监听本地地址且端口号为8888server = new ServerSocket(8888);b_serverStart = true;} catch (IOException e) {//解决打开多个Server端的情况System.out.println("请关闭已经打开的Server端,重新开启");System.exit(0);}while(b_serverStart){//等待客户端的连接,如果没有获取连接  Socket client = null;try {client = server.accept();} catch (IOException e) {e.printStackTrace();}  System.out.println("与客户端连接成功!");  //为每个客户端连接开启一个线程  ServerThread st = new ServerThread(client);serverThreads.add(st);new Thread(st).start();  }try {server.close();} catch (IOException e) {e.printStackTrace();}}private class ServerThread implements Runnable{private Socket client = null;private DataInputStream dis = null;private DataOutputStream dos = null;private boolean b_connect = false;public  ServerThread(Socket client) {this.client=client;try {dis = new DataInputStream(this.client.getInputStream());dos = new DataOutputStream(client.getOutputStream()); b_connect=true;} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() { try{while(b_connect){  //接收从客户端发送过来的数据  String str= dis.readUTF();if(str == null || "".equals(str)){  b_connect = false;  }else{  if("bye".equals(str)){  b_connect = false;  }else{  //将接收到的字符串前面加上输出到控制台System.out.println(str);//将Client端发送过来的数据广播出去for(int i=0;i<serverThreads.size();i++){ServerThread st = serverThreads.get(i);st.send(str);}}  }  }}catch(IOException e){System.out.println("client端关闭了");//e.printStackTrace();}finally{try{if(dis!=null) dis.close();if(dos!=null) dos.close();if(client!=null) client.close();}catch(IOException e){e.printStackTrace();}               }}private void send(String str) {//如果发送数据发生异常,则说明此连接已经不再,则需要在Server端将此Client移除try {this.dos.writeUTF(str);} catch (IOException e) {serverThreads.remove(this);}}           }}

而在client 端,只需要不停的接收来自于服务器端的数据即可。

代码如下:

    public class ChatClient extends JFrame{private TextField tf = null;private TextArea ta = null;private Socket client =null;private DataOutputStream  dos = null;private DataInputStream dis = null;private boolean b_conn =false;public static void main(String[] args) {new ChatClient().launch();}private void launch() {this.setTitle("client端");this.setLocation(300, 400);this.setSize(300, 400);/** 关闭窗口的两种方法* *///this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addWindowListener(new WindowAdapter(){//为了关闭窗口public void windowClosing(WindowEvent e){disconnect();System.exit(0);}});tf=new TextField();ta=new TextArea();//为TextField添加回车事件响应tf.addActionListener(new ClientLisenter());this.add(BorderLayout.SOUTH,tf);this.add(BorderLayout.NORTH, ta);pack();//窗口自动适应大小,使窗口能正好显示里面所有的控件。this.setVisible(true);connect();//连接上了之后,开启一个线程来进行接收服务器端的数据new Thread(new RecvThread()).start();}private class RecvThread implements Runnable{@Overridepublic void run() {while(b_conn){String str = null;//从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常  try {str = dis.readUTF();//将信息写入到TextArea中ta.setText(ta.getText()+str+'\n');}catch(SocketException e1){System.out.println("bye");}catch (EOFException e) {System.out.println("推出了,bye - bye!");}catch (IOException e) {System.out.println("我关闭了也");e.printStackTrace();}}}}private void connect() {//客户端请求与本机在8888端口建立TCP连接 try {client = new Socket("127.0.0.1", 8888);//client.setSoTimeout(10000); dos = new DataOutputStream(client.getOutputStream());dis = new DataInputStream(this.client.getInputStream());b_conn = true;} catch (UnknownHostException e) {System.out.println("没有找到需要连接的主机!!");e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void disconnect(){  try {b_conn = false;if(dos!=null) dos.close();if(client!=null) client.close();} catch (IOException e) {e.printStackTrace();}}private class ClientLisenter implements ActionListener{@Overridepublic void actionPerformed(ActionEvent event) {String content = tf.getText();/** 判断TextArea中是否有内容,如果有,则需要先加入一个换行符,* 然后再加入内容,否则直接加入内容* *///由于服务器端会广播其发送的消息,因此,就不需要再这里完成显示了//                  if(ta.getText().trim().length()!=0){//                      ta.setText(ta.getText()+"\n"+content);//                  }//                  else{//                      ta.setText(content);//                  }//                  tf.setText("");try {dos.writeUTF(content);dos.flush();} catch (IOException e) {e.printStackTrace();}}}}

以上就完成过来简单的聊天程序,可能有的人会说,这个实现的是广播信息,而不是我们在QQ中常见的一对一的发送消息,其实道理一样,我们只需要在Client端在发送消息时将目的地址加上,Server端也同样是进行广播。而在其它所有的Client端检测消息中的地址是不是我们自己本身,如果是,则将消息接收过来,否则,不进行接收。当然,这种方法并不是一种好的解决方法,还有其它的实现点对点通信更好的方法。

与博文相关的全部代码可以在这里获取:
https://github.com/wojiushimogui/chat 。

参考资料

1、马士兵的相关视频

2、博客:http://blog.sina.com.cn/s/blog_67d440ab0101hcoz.html

《Java项目实践》:简单聊天程序相关推荐

  1. java和matlab的交互实践--在java项目中调用matlab程序

    本文主要解决了java项目中调用matlab程序过程中遇到的问题,下文主要分matlab的jar包部署以及java项目配置两个方面来分析. 1.matlab项目的部署 -- 生成jar包 保存matl ...

  2. 手把手教你从0到1进行Java项目实践

    手把手教你从0到1进行Java项目实践 虽说工作就是简单的事情重复做,但不是所有简单的事你都能有机会做的. 我们平日工作里,大部分时候都是在做修修补补的工作,而这也是非常重要的.做好修补工作,做好优化 ...

  3. 计算机网络课程设计聊天,计算机网络课程设计-简单聊天程序.doc

    计算机网络课程设计-简单聊天程序 黔南民族师范学院 计算机科学系 计算机网络课程设计报告 课题名称: 简单聊天程序 姓 名: 学 号: 专业班级: 系 (院): 计算机科学系 指导老师: 设计时间: ...

  4. JAVA编写的简单计算器程序

    系列文章目录 文章目录 系列文章目录 前言 一.JAVA编写的简单计算器程序 前言 链接:https://pan.baidu.com/s/1oPJRIbwxcXgewZ_KZaWzTg 提取码:egy ...

  5. java聊天程序论文_【基于java的仿qq聊天程序的设计与实现论文最终版材料】

    基于java的仿qq聊天程序的设计与实现(论文)(最终版) <基于java的仿qq聊天程序的设计与实现(论文).doc>由会员分享,可免费在线阅读全文,更多与<基于java的仿qq聊 ...

  6. Java案例:基于TCP的简单聊天程序

    文章目录 一.如何实现TCP通信 二.编写C/S架构聊天程序 (一)编写服务器端程序 - Server.java (二)编写客户端程序 - Client.java (三)测试服务器端与客户端能否通信 ...

  7. 2022.11.22 flaks项目开发-简单聊天机器人

    介绍: 1.简单聊天机器人功能:1.在输入框中输入你的语句,机器人会自动回答你的问题 2.static文件夹保存静态文件templates文件夹保存html代码sample.py是程序源代码及程序入口 ...

  8. java 网络编程简单聊天_网络编程之 TCP 实现简单聊天

    网络编程之 TCP 实现简单聊天 客户端 1.连接服务器 Socket 2.发送消息 package lesson02;import java.io.IOException;import java.i ...

  9. Java项目:微信小程序商城+后台管理系统

    作者主页:夜未央5788 简介:Java领域优质创作者.Java项目.学习资料.技术互助 文末获取源码 项目介绍 本项目为小程序商城系统前后台,前台为普通会员用户登录,后台为管理员登录: 程序功能: ...

最新文章

  1. Android--百度地图密钥申请+环境配置(一)
  2. accesskey 提交
  3. Python 操作数据库(1)
  4. 7-1 作业调度算法--先来先服务
  5. 网络协议——TCP/IP协议
  6. Python 最佳实践
  7. OpenCV立体声匹配 stereo matching将L和R图像转换为视差和点云的实例(附完整代码)
  8. 《算法与数据结构专场》BitMap算法介绍
  9. 用简单的方法构建一个高可用服务端
  10. Objective-C 学习记录6--dictionary
  11. Window上安装kafka
  12. erlang supervisor中启动普通的进程
  13. 明翰英语教学系列之PTE与多邻国篇V1.1
  14. 【Windows】PPT播放视频提示媒体不可用的解决方法
  15. arcpy批量合并融合矢量数据
  16. 汇编语言期末复习不挂科——知识点总结
  17. swoole 点对点发送消息推送
  18. 自媒体攻略合集,教你如何做一名能赚钱的自媒体人
  19. 文字,字体,图像,列表
  20. 【谷粒商城基础篇】仓储服务:仓库维护

热门文章

  1. 《计算机工程与应用》投稿详解
  2. 比较好的pdf转换成txt转换器
  3. finereport php,FineReport与Web集成
  4. Redhat安装完成后,注册激活方法
  5. stable diffusion实战技巧
  6. 【JVM进阶之路】五:垃圾回收概述和对象回收判定
  7. 兰州一中计算机教室,兰州一中2019年中青年教师研究课暨高考复习研讨课活动...
  8. log4cplus库(一)(简单使用)
  9. 亚马逊云科技依托人工智能进行游戏数据分析,解决游戏行业痛点,助力游戏增长
  10. 文艺清新简约教师公开课PPT模板