基于服务器转发的聊天程序
1. 实验目的:
基于java编程使用套接字socket,掌握服务器与客户端通信技术,多线程的使用。
2. 实验内容:
实现服务器转发由客户端发送来的数据,包括群发数据和点对点的发送数据完成私聊和群聊的通信效果。
3. 实验代码:
Server:
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
import java.net.SocketException; import java.util.ArrayList;
//编写服务器端
public class ServerSocketTest extends Thread {
public void read() {// 此方法专门负责读取客户端用户发送消息
InputStream in = null; try {
// 获得客户端的输入的字节流对象 in = socket.getInputStream();// 输入字节流 String ip = socket.getInetAddress().getHostAddress();
public void run() { }
read();
public ServerSocketTest(Socket socket) {// 有参构造器,它是初始化全局变量socket对象 }
this.socket = socket;
public Socket socket;// 为read()方法服务的
public static ArrayList 对象的 1/11 基于服务器转发的聊天程序 public void write(byte[] buff, int len, String ip) {// 专门负责将用户发到服务器的消息转发给其它用户 OutputStream out = null; try { for (int i = 0; i < sockets.size(); i++) { Socket socket = sockets.get(i); out = socket.getOutputStream(); String msg = new String(buff, 0, len); if (msg.startsWith(\"@\")) {//判断是否是私聊 String[] str = msg.split(\":\"); String addr = str[0].substring(1, str[0].length()); System.out.println(addr); if (addr.equals(socket.getInetAddress().getHostAddress())) { out.write((ip+\"私\"+msg).getBytes()); continue; } else } } System.out.println(\"用户\"+ip+\"连接上\"); byte[] buff = new byte[1024]; int len = 0; while ((len = in.read(buff)) != -1) { } System.out.println(\"read()方法提示:\" + socket.getInetAddress().getHostAddress() + \"用户已经下线~\"); sockets.remove(socket); if (sockets.isEmpty()) System.out.println(\"当前没有用户连接服务器\"); System.out.println(ip + \":\" + new String(buff, 0, len));// 测试客户端是否把信息发送到了write(buff, len, ip); 服务器端来 } catch (SocketException e) { } catch (Exception e) { e.printStackTrace(); if (in != null) { } try { } in.close(); e.printStackTrace(); } catch (IOException e) { } finally { } else {//群发 msg = ip + \":\" + msg; 2/11 基于服务器转发的聊天程序 } public static void main(String[] args) { } try { } // 创建服务器套接字对象(端口9999) ServerSocket serverSocket = new ServerSocket(9999); while (true) { } e.printStackTrace(); // 当用户连上服务器后就会得到一个客户端套接字对象 Socket socket = serverSocket.accept(); sockets.add(socket);// 连接上的用户的套接字对象保存到集合中 ServerSocketTest sst = new ServerSocketTest(socket); sst.start(); } } } e.printStackTrace(); } try { } out.write(msg.getBytes()); System.out.println(\"write方法提示:有个用户已经下线~\"); } catch (SocketException e) { } catch (Exception e) { } catch (IOException e) { Client: import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import javax.swing.text.BadLocationException; import javax.swing.text.StyledDocument; 3/11 基于服务器转发的聊天程序 public class NewJFrame extends javax.swing.JFrame implements Runnable { public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub if (e.isControlDown() inputArea.addKeyListener(// 为当前窗体注册一个键盘事件 new KeyListener() { jButton2.setText(\"关闭\"); jButton2.addActionListener(new ActionListener() { }); public void actionPerformed(ActionEvent e) { } System.exit(0); jScrollPane1 = new javax.swing.JScrollPane(); inputArea = new javax.swing.JTextArea();// 用户输入的内容存放组件 jScrollPane2 = new javax.swing.JScrollPane(); showPane = new javax.swing.JTextPane(); showPane.setText(\"显示窗口\" + \"\\n\"); showPane.setEditable(false);// 禁止在聊天记录窗口输入数据 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jButton2 = new javax.swing.JButton(); jButton3 = new javax.swing.JButton(); sendBut = new javax.swing.JButton(); private void initComponents() { public NewJFrame() {// 构造器 } initComponents(); private javax.swing.JButton jButton2; private javax.swing.JButton jButton3; private javax.swing.JButton sendBut; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea inputArea; private static javax.swing.JTextPane showPane; private static OutputStream out; public static Socket socket; public static InputStream in; 4/11 基于服务器转发的聊天程序 sendBut.setText(\"发送\"); // 为sendBut这对象注册一个单击事件 }); }); public void keyTyped(KeyEvent e) { } // TODO Auto-generated method stub } public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } } && e.getKeyCode() == KeyEvent.VK_ENTER) { String msg = inputArea.getText();// 获取输入框的值 inputArea.setText(\"\");// 清空输入框 inputArea.requestFocus();// 获取当前焦点 try { } out.write(msg.getBytes());// 把用户输入的消息发送到服务器 // 回显本窗口向服务器发送的数据 if (msg.startsWith(\"@\")) { } e1.printStackTrace(); StyledDocument doc = showPane try { } doc.insertString(doc.getLength(), \"我\" + msg + \"\\n\ .getStyledDocument(); .getLength());// 文本向下移动 showPane.select(doc.getLength(), doc } catch (BadLocationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { jButton2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } showPane.setText(\"\"); 5/11 基于服务器转发的聊天程序 javax.swing.GroupLayout layout = new javax.swing.GroupLayout( getContentPane()); getContentPane().setLayout(layout); layout inputArea.setColumns(20); inputArea.setRows(5); jScrollPane1.setViewportView(inputArea); jScrollPane2.setViewportView(showPane); jButton3.setText(\"清空记录\"); jButton3.addActionListener(new ActionListener() { }); public void actionPerformed(ActionEvent e) { } showPane.setText(\"\"); }); } } catch (IOException e1) { } e1.printStackTrace(); // 回显本窗口向服务器发送的数据 if (msg.startsWith(\"@\")) { } StyledDocument doc = showPane.getStyledDocument(); showPane.select(doc.getLength(), doc.getLength());// 文本向下移动 try { } doc.insertString(doc.getLength(), \"我说\" + msg + \"\\n\ try { out.write(msg.getBytes());// 把用户输入的消息发送到服务器 sendBut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String msg = inputArea.getText();// 获取输入框的值 inputArea.setText(\"\");// 清空输入框 inputArea.requestFocus();// 获取当前焦点 } catch (BadLocationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); 6/11 基于服务器转发的聊天程序 .setHorizontalGroup(layout .createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) layout.createSequentialGroup().addContainerGap( javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(jButton2) .addGap(18, 18, 18).addComponent( sendBut).addGap(22, 22, 22) 14)) .addComponent(jButton3).addGap(14, 14, .addGroup( .addGroup( layout .createSequentialGroup() .addContainerGap() .addGroup( layout .createParallelGroup( .addComponent( .addComponent( 678, jScrollPane1, jScrollPane2, javax.swing.GroupLayout.Alignment.LEADING) javax.swing.GroupLayout.Alignment.TRAILING) javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap())); layout .setVerticalGroup(layout .createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) javax.swing.GroupLayout.Alignment.TRAILING, layout .createSequentialGroup() .addContainerGap() .addComponent( jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, .addGroup( 7/11 基于服务器转发的聊天程序 // 注意先后次序,不可以放在前面 new NewJFrame().setVisible(true);// 显示窗口 } NewJFrame jf = new NewJFrame(); Thread thread = new Thread(jf); thread.start(); e.printStackTrace(); e.printStackTrace(); try { socket = new Socket(\"172.16.72.189\out = socket.getOutputStream(); in = socket.getInputStream(); public static void main(String args[]) { // 1.先到得socket对象 2.通过socket对象得到outputStream对象 } pack(); 212, Short.MAX_VALUE) .addGap(30, 30, 30) .addComponent( .addPreferredGap( .addGroup( layout .createParallelGroup( .addComponent(sendBut) .addComponent(jButton3) .addComponent(jButton2)) 114, jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) javax.swing.GroupLayout.Alignment.LEADING) .addContainerGap())); } catch (UnknownHostException e) { } catch (IOException e) { 8/11 基于服务器转发的聊天程序 } public void run() { } // TODO Auto-generated method stub read(); } public void read() {// 读取服务器传过来的消息 try { } // finally { // if (in != null) { // try { // in.close(); // } catch (IOException e) { // e.printStackTrace(); // } // } // } byte[] buff = new byte[1024]; int len = 0; while ((len = in.read(buff)) != -1) { } e.printStackTrace(); // 接收从服务器端发送过来的数据并显示在showPane框中 StyledDocument doc = showPane.getStyledDocument(); showPane.select(doc.getLength(), doc.getLength());// 文本向下移动 doc.insertString(doc.getLength(), new String(buff, 0, len) + \"\\n\ } } catch (Exception e) { 4. 实验结果: 初始界面: 9/11 基于服务器转发的聊天程序 客户端一号(172.16.72.197) 客户端二号(172.16.72.166) 10/11 基于服务器转发的聊天程序 服务器端: 注:发送消息可使用快捷键Ctrl+Enter; 源代码见附件。 5. 实验总结: 经过为期三天的学习并编写此次课程设计,让我更深入地了解了C/S模式,也认识到了Java语言的强大魅力,我相信在以后对Java语言的更深入研究中,我会加倍努力认真学习,使自己尽快成长为一个Java程序员的标准水平。 首先感谢==大学给与的这次培训机会,感谢==公司的通力合作,感谢恩师==老师的悉心指导! 11/11 因篇幅问题不能全部显示,请点此查看更多更全内容