用java socket做一个聊天室,实现多人聊天的功能。看了极客学院的视频后跟着敲的。(1DAY)
服务端:
1. 先写服务端的类MyServerSocket,里面放一个监听线程,一启动就好
2. 实现服务端监听类ServerListener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例ChatSocket。启动线程后就把线程交给ChatManager管理
3. 在ChatSocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端
4. ChatManager里面用vector来管理socket线程实例ChatSocket,并实现发送信息给其他的客户端
客户端:
1. 新建一个继承JFrame的MainWindow.java类,主要实现聊天窗口的UI,以及事件响应。
2. 新建StartClient.java类,把MainWindow中生成MainWindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。
3. 新建ChatManager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到ChatManager中,才能实现ChatManager对界面的显示。
工程结构如图
以下为代码
服务端:
1. 先写服务端的类MyServerSocket,里面放一个监听线程,一启动就好
package com.starnet.testserversocket.main; public class MyServerSocket { public static void main(String[] args) { new ServerListener().start(); } }
2.实现服务端监听类ServerListener.java,用accept来监听,一旦有客户端连上,生成新的socket,就新建个线程实例ChatSocket。启动线程后就把线程交给ChatManager管理
package com.starnet.testserversocket.main; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import javax.swing.JOptionPane; public class ServerListener extends Thread { public void run() { try { ServerSocket serverSocket = new ServerSocket(23456); while (true) { // block Socket socket = serverSocket.accept(); // 建立链接 JOptionPane.showMessageDialog(null, "有客户端连到本机23456端口"); //将socket传递给新的线程 ChatSocket cs= new ChatSocket(socket); cs.start(); ChatManager.getChatManager().add(cs); } } catch (IOException e) { e.printStackTrace(); } } }
3.在ChatSocket中实现从客户端读取内容,把读取到的内容发给集合内所有的客户端
package com.starnet.testserversocket.main; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.Socket; /*每一个连上的客户端,服务器都有一个线程为之服务*/ public class ChatSocket extends Thread { Socket socket; public ChatSocket(Socket s) { this.socket = s; } //发送数据 public void out(String out) { try { socket.getOutputStream().write(out.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //服务器会不断地从客户端读取内容,把读取到的内容发给集合内所有的客户端。 public void run() { try { //接收数据 BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream(), "UTF-8")); String line=null; //发送读到的内容 while ((line = br.readLine())!=null) { System.out.println(line); ChatManager.getChatManager().publish(this, line); } br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
4.ChatManager里面用vector来管理socket线程实例ChatSocket,并实现发送信息给其他的客户端
package com.starnet.testserversocket.main; import java.util.Vector; //一个聊天服务器只能有一个manager,要单例化处理 public class ChatManager { private ChatManager(){} private static final ChatManager CM=new ChatManager(); public static ChatManager getChatManager(){ return CM; } Vectorvector = new Vector (); /*增加ChatSocket 实例到vector中*/ public void add(ChatSocket cs){ vector.add(cs); } /*发布消息给其他客户端 *ChatSocket cs: 调用publish的线程 *msg:要发送的信息 */ public void publish(ChatSocket cs, String msg){ for (int i = 0; i
客户端:
1. 新建一个继承JFrame的MainWindow.java类,主要实现聊天窗口的UI,以及事件响应。
package com.starnet.javaclient.view; import java.awt.BorderLayout; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.JTextArea; import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.JTextField; import javax.swing.JButton; import javax.swing.LayoutStyle.ComponentPlacement; import com.starnet.javaclient.main.ChatManager; import com.sun.xml.internal.ws.client.SenderException; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class MainWindow extends JFrame { /** * */ private static final long serialVersiOnUID= 1L; private JPanel contentPane; private JTextArea txt; private JTextField txtip; private JTextField txtSend; /** * Create the frame. */ public MainWindow() { setAlwaysOnTop(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); cOntentPane= new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); txt = new JTextArea(); txt.setText("ready..."); txtip = new JTextField(); txtip.setText("127.0.0.1"); txtip.setColumns(10); JButton btnCOnnect= new JButton("connect"); btnConnect.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { ChatManager.getChatManager().connect(txtip.getText()); } }); txtSend = new JTextField(); txtSend.setText("hello"); txtSend.setColumns(10); JButton btnSend = new JButton("send"); btnSend.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { ChatManager.getChatManager().send(txtSend.getText()); appendText("我说: "+txtSend.getText()); txtSend.setText(""); } }); GroupLayout gl_cOntentPane= new GroupLayout(contentPane); gl_contentPane.setHorizontalGroup( gl_contentPane.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup() .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING) .addGroup(gl_contentPane.createSequentialGroup() .addComponent(txtSend, GroupLayout.DEFAULT_SIZE, 325, Short.MAX_VALUE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(btnSend, GroupLayout.PREFERRED_SIZE, 109, GroupLayout.PREFERRED_SIZE)) .addGroup(Alignment.LEADING, gl_contentPane.createSequentialGroup() .addComponent(txtip, GroupLayout.PREFERRED_SIZE, 294, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(btnConnect, GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)) .addComponent(txt, GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE)) .addContainerGap()) ); gl_contentPane.setVerticalGroup( gl_contentPane.createParallelGroup(Alignment.LEADING) .addGroup(gl_contentPane.createSequentialGroup() .addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE) .addComponent(txtip, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(btnConnect)) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(txt, GroupLayout.DEFAULT_SIZE, 198, Short.MAX_VALUE) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING) .addComponent(btnSend) .addComponent(txtSend, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))) ); contentPane.setLayout(gl_contentPane); } /*客户端发送的内容添加到中间的txt控件中*/ public void appendText(String in) { txt.append("\n" + in); } }
2.新建StartClient.java类,把MainWindow中生成MainWindow主方法部分代码拷贝过来,这样就能在主程序中把窗体执行出来了。
package com.starnet.javaclient.main; import java.awt.EventQueue; import com.starnet.javaclient.view.MainWindow; public class StartClient { public static void main(String[] args) { /*先新建一个jframe,然后把自动生成的代码贴过来*/ EventQueue.invokeLater(new Runnable() { public void run() { try { MainWindow frame = new MainWindow(); frame.setVisible(true); //创建完这个frame以后,传一份window的引用到ChatManager去 ChatManager.getChatManager().setWindow(frame); } catch (Exception e) { e.printStackTrace(); } } }); } }
3.新建ChatManager(需要单例化的类)管理socket,实现聊天的输入输出功能。最后记得在1中新建窗口后,传一份frame的引用到ChatManager中,才能实现ChatManager对界面的显示。
package com.starnet.javaclient.main; 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.net.UnknownHostException; import com.starnet.javaclient.view.MainWindow; public class ChatManager { private ChatManager(){} private static final ChatManager instance=new ChatManager(); public static ChatManager getChatManager(){ return instance; } MainWindow window;//为了能在界面上显示服务器发来的信息,就需要传一个MainWindow的引用进来 Socket socket; private String IP; BufferedReader bReader; PrintWriter pWriter; public void setWindow(MainWindow window) { this.window = window; window.appendText("文本框已经和chatManager绑定了"); } public void connect(String ip) { this.IP = ip; new Thread(){ @Override public void run() { //实现网络方法 try { socket = new Socket(IP, 23456); //输出流 pWriter = new PrintWriter( new OutputStreamWriter( socket.getOutputStream())); //输入流 bReader = new BufferedReader( new InputStreamReader( socket.getInputStream())); String line = null; //如果读取数据为空 while ((line = bReader.readLine())!=null) { window.appendText("收到: "+line); } //读完数据之后要关闭 pWriter.close(); bReader.close(); pWriter = null; bReader = null; } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } public void send(String sendMsg){ if (pWriter!=null) { pWriter.write(sendMsg+"\n"); pWriter.flush(); } else { window.appendText("当前链接已经中断..."); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。