Socket群聊代码

       写得不是很规范,但也写挺多的注释了。一般是可以看得懂的啦。没什么特别的功能,仅仅是群聊!ps:玩玩而已。直接贴代码。。。比较适合刚学Socket编程的看。界面的代码是用Netbean直接生成的,显得很笨重!

Code:
  1. //====================Server.java=================================   
  2.   
  3. package cc.nothing2012.blogServlet;   
  4.   
  5. import java.io.DataInputStream;   
  6. import java.io.DataOutputStream;   
  7. import java.io.IOException;   
  8. import java.net.InetAddress;   
  9. import java.net.ServerSocket;   
  10. import java.net.Socket;   
  11. import java.util.Vector;   
  12.   
  13. public class Server {   
  14.  private ServerSocket serverSocket;   
  15.  private Socket socket;   
  16.  private static Vector<ServerObject> vector = new Vector<ServerObject>();   
  17.  private ServerObject serverObject;   
  18.   
  19.  private static Vector<String> vecIPs = new Vector<String>();   //记录所有的IP对象   
  20.  public Server() {   
  21.   try {   
  22.    serverSocket = new ServerSocket(55555);   
  23.    System.out.println("服务器已经启动!"); // 后台提示   
  24.    while (true) {   
  25.     try {   
  26.      socket = serverSocket.accept(); // 一直在等待连接   
  27.      p(socket);   
  28.      final InetAddress address = socket.getInetAddress();   
  29.      p("那个丫的连接的IP:" + address);   
  30.      p(vector.size()); // 打印连接前,登陆客户端的个数。   
  31.      serverObject = new ServerObject( socket); // 说明一个客户端连接上了, 新建对象线程。   
  32.      vector.addElement(serverObject); // 往向量里面添加一个客户端。   
  33.         
  34.      p("add"+address.getHostAddress());   
  35.      vecIPs.addElement("add"+address.getHostAddress());                
  36.      serverObject.start(); // 启动一个线程   
  37.      p("客户端个数:"+vector.size()); // 打印连接后,登陆客户端的个数。   
  38.      p("IP个数:"+vecIPs.size());   
  39.     } catch (IOException e) {   
  40.      e.printStackTrace();   
  41.     }   
  42.    }   
  43.   } catch (IOException e) {   
  44.    p("服务器启动失败!");   
  45.   }   
  46.  }   
  47.   
  48.  public void p(Object o) {   
  49.   System.out.println(o);   
  50.  }   
  51.   
  52.  public static void main(String[] args) {   
  53.         new Server();   
  54.  }   
  55.   
  56.  class ServerObject extends Thread {   
  57.   private DataOutputStream out = null;   
  58.   private DataInputStream in = null;   
  59.   private Socket socket=null;   
  60.   
  61.   // 每个连接过来的客户端,将初始化这样的一个对象。   
  62.   public ServerObject( Socket socket) {   
  63.    this.socket=socket;   
  64.    try {   
  65.     in = new DataInputStream(socket.getInputStream());   
  66.     out = new DataOutputStream(socket.getOutputStream());   
  67.    } catch (IOException e) {   
  68.     e.printStackTrace();   
  69.    }   
  70.       
  71.   }   
  72.   
  73.   public void initIPs(){    //无论是增加还是减少都用此方法来更新在线用户   
  74.    String allIPs="";   
  75.    for(int i=0;i<vecIPs.size();i++){   //vecIPs至少为1,故不判空   
  76.     allIPs=allIPs.concat(vecIPs.get(i));    //把ip地址都存放在一个字符串里面   
  77.    }   
  78.    try {   
  79.     for(int i=0;i<vector.size();i++){   
  80.      Server.vector.get(i).out.writeUTF(allIPs); // 输出信息给每个客户端。   
  81.     }   
  82.    } catch (IOException e1) {   
  83.     e1.printStackTrace();   
  84.    }    
  85.   }   
  86.   // 启动线程时,执行   
  87.   public void run() {   
  88.    boolean flag = true// 只是一个标志   
  89.    int m;   
  90.    //根据当前的在线用户刷新,在线的用户。每个对象只初始化一次!    
  91.    initIPs();   
  92.    while (flag) {   
  93.     try {        
  94.      String message = in.readUTF(); // 输入进来的流,简称输入流,拿到客户端的信息。   
  95.      System.out.println("IP是"+socket.getInetAddress().getHostAddress()+"的"+message);        // 后台打印出来   
  96.      if (message.equals("exit")) {// 如果接收到"exit"字符串说明运行该线程的客户端断开了连接 ,则需退出该循环,退出线程   
  97.       flag = false;        // 退出循环(指的是本通道关闭,该对象的进程结束)   
  98.          
  99. //      try{   
  100. //       Server.vecIPs.remove(this);  //从vecIPs中除去本对象的IPs,   估计会出错这儿。   
  101. //      }catch(NullPointerException ee){   
  102. //       System.out.println("果然出错");   
  103. //       ee.printStackTrace();        
  104. //      }   
  105.       String tempIP="add"+socket.getInetAddress().getHostAddress();//把此IP从ip向量表里咔嚓掉   
  106.       for(int i=0;i<vecIPs.size();i++){   
  107.        if(vecIPs.get(i).equals(tempIP)){   
  108.         vecIPs.remove(i);   
  109.         break;   
  110.        }   
  111.       }   
  112.       Server.vector.remove(this); // 当客户端关闭时,从Vector里除去本对象   
  113.          
  114.       initIPs();       //重新初始化各个客户端。   
  115.      } else {   
  116.       m = Server.vector.size(); // 返回共有多少个客户端目前。   
  117.       for (int i = 0; i < m; i++) { // 给每个客户端发送同样的信息。   
  118.        Server.vector.get(i).out.writeUTF(message); // 输出信息给每个客户端。   
  119.       }   
  120.      }   
  121.     } catch (IOException e) {   
  122.      e.printStackTrace();   
  123.     }   
  124.    }   
  125.   }   
  126.  }   
  127. }   
  128.   

 

Code:
  1. //===================MyJFrame2.java===============================   
  2.   
  3. package cc.nothing2012.blogServlet;   
  4.   
  5. import java.awt.event.ActionEvent;   
  6. import java.awt.event.ActionListener;   
  7. import java.awt.event.KeyAdapter;   
  8. import java.awt.event.KeyEvent;   
  9. import java.awt.event.WindowAdapter;   
  10. import java.awt.event.WindowEvent;   
  11. import java.io.DataInputStream;   
  12. import java.io.DataOutputStream;   
  13. import java.io.IOException;   
  14. import java.net.Socket;   
  15. import java.net.UnknownHostException;   
  16. import java.util.Timer;   
  17. import java.util.TimerTask;   
  18. import java.util.Vector;   
  19. import java.util.regex.Matcher;   
  20. import java.util.regex.Pattern;   
  21.   
  22.   
  23. public class MyJrame2 extends javax.swing.JFrame implements Runnable  {   
  24.  public static Vector<String> vectorIP = new Vector<String>();   
  25.  public static Vector<String> vectorIPtemp = new Vector<String>();   
  26.     
  27.  private Socket socket;   
  28.  private DataInputStream in;   
  29.  private DataOutputStream out;   
  30.  private boolean flag = true// 标志 如果多个客户端则会出错。   
  31.   
  32.  private boolean serverClose = false;// 标识服务器端是否关闭,true为关闭,false为没关闭   
  33.   
  34.  private static final long serialVersionUID = 1L;   
  35.     public MyJrame2() {   
  36.         initComponents();   //用来初始化界面   
  37.         contorClient();      //连接服务器等操作   
  38.   // this.getRootPane().setDefaultButton(jToggleButton1);   
  39.   
  40.   new Timer().schedule(new TimerTask() {   
  41.    public void run() {   
  42.     // for(int i=0;i<vectorIP.size();i++){   
  43.     // System.out.println(vectorIP.get(i));   
  44.     // }   
  45.     // System.out.println(vectorIP.size());   
  46.     jList1.setListData(vectorIP);   
  47.    }   
  48.   }, 20003000);   
  49.     }   
  50.     public String getMessage() {   
  51.   if (!(jTextField2.getText()).equals("")) { // 如果写的东西不为空   
  52.    if (!(jTextField1.getText()).equals("")) { // 判断是谁写的信息   
  53.     return (jTextField1.getText() + ": " + jTextField2.getText());   
  54.    } else {   
  55.     return ("默认是骚包: " + jTextField2.getText()); // 无名氏默认是ClientX   
  56.    }   
  57.   } else { // 什么都没写   
  58.    return "";   
  59.   }   
  60.  }   
  61.   
  62.  public void setMessage(String message) {   
  63.   jTextArea1.append(message + "/n"); // 添加信息并换行。   
  64.  }   
  65.   
  66.  public void contorClient() {   
  67.   try {   
  68.    socket = new Socket("xxx.xx.xxx.xxx"55555); //此处新建了一个Socket,并连接服务器   
  69.                // 。通信从此位置开始。   
  70.    jButton1.addActionListener(new ActionListener() { // “发送”按钮监听   
  71.       public void actionPerformed(ActionEvent e) { // 监听按钮的方法。   
  72.                   // 必须实现的   
  73.                   // 。   
  74.        try {   
  75.         if (!serverClose) { // 第一次执行时,默认是开着的。之后,如果服务器开着,   
  76.              // 即没有关闭,则发送下面内容   
  77.          String message = getMessage(); // 取得某人写的某些内容   
  78.          if (!message.equals("")) {   
  79.           out = new DataOutputStream(socket   
  80.             .getOutputStream());   
  81.           out.writeUTF(message); // 把message通过s输出去   
  82.           jTextField2.setText(""); // 此处只有发送按钮在监听,   
  83.                  // 故发送之后   
  84.                  // ,内容理应删掉。   
  85.          }   
  86.         }   
  87.        } catch (IOException ioe) {   
  88.         ioe.printStackTrace();   
  89.        }   
  90.       }   
  91.      });   
  92.    this.addWindowListener(new WindowAdapter() { // 监听客户端是否关闭,如果关闭,   
  93.                // 则向服务器发送一个   
  94.                // “exit”字符串   
  95.       public void windowClosing(WindowEvent e) {   
  96.        try {   
  97.         if (serverClose) { // serverClose 的值一直都是false。   
  98.          // 此处永远不会被执行。   
  99.         } else { // 因为监听到了窗口被关闭了。   
  100.          out = new DataOutputStream(socket   
  101.            .getOutputStream());   
  102.          out.writeUTF("exit"); // 既然关闭了,就发送个信号给服务器。   
  103.          // 删除该客户端。   
  104.         }   
  105.        } catch (IOException e1) {   
  106.         e1.printStackTrace();   
  107.        }   
  108.       }   
  109.      });   
  110.    //只是实现了enter键的触发而已。   
  111.    jTextField2.addKeyListener(new KeyAdapter() {   
  112.     public void keyPressed(KeyEvent event) {   
  113.      if (event.getKeyCode() == KeyEvent.VK_ENTER) {   
  114.       try {   
  115.        if (!serverClose) { //第一次执行时,默认是开着的。之后,如果服务器开着,即没有关闭   
  116.             // ,则发送下面内容   
  117.         String message = getMessage(); // 取得某人写的某些内容   
  118.         if (!message.equals("")) {   
  119.          out = new DataOutputStream(socket   
  120.            .getOutputStream());   
  121.          out.writeUTF(message); // 把message通过s输出去   
  122.          jTextField2.setText(""); //此处只有发送按钮在监听,故发送之后   
  123.                 // ,内容理应删掉。   
  124.         }   
  125.        }   
  126.       } catch (IOException ioe) {   
  127.        ioe.printStackTrace();   
  128.       }   
  129.      }   
  130.     }   
  131.    });   
  132.   
  133.    new Thread(this).start(); // 打开一个线程,即执行本类的run()函数。   
  134.   } catch (UnknownHostException e) {   
  135.    e.printStackTrace();// 打印出错信息而已,别无他意。   
  136.   } catch (IOException e) {   
  137.    serverClose = true;   
  138.    setMessage("服务器不存在或未打开!");   
  139.   }   
  140.  }   
  141.     
  142.     private void initComponents() {   
  143.         jLabel1 = new javax.swing.JLabel();   
  144.         jTextField1 = new javax.swing.JTextField();   
  145.         jLabel2 = new javax.swing.JLabel();   
  146.         jScrollPane1 = new javax.swing.JScrollPane();   
  147.         jTextArea1 = new javax.swing.JTextArea();   
  148.         jTextField2 = new javax.swing.JTextField();   
  149.         jButton1 = new javax.swing.JButton();   
  150.         jScrollPane2 = new javax.swing.JScrollPane();   
  151.         jList1 = new javax.swing.JList();   
  152.         setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);   
  153.         setTitle("八卦聊天器");   
  154.         setBackground(new java.awt.Color(204204255));   
  155.         jLabel1.setFont(new java.awt.Font("宋体"018)); // NOI18N   
  156.         jLabel1.setText("请输入您的昵称:");   
  157.         jTextField1.setFont(new java.awt.Font("宋体"018)); // NOI18N   
  158.         jTextField1.setForeground(new java.awt.Color(204204255));   
  159.         jLabel2.setFont(new java.awt.Font("宋体"018)); // NOI18N   
  160.         jLabel2.setText("在线用户IP:");   
  161.         jTextArea1.setColumns(20);   
  162.         jTextArea1.setRows(5);   
  163.         jScrollPane1.setViewportView(jTextArea1);   
  164.         jButton1.setFont(new java.awt.Font("宋体"018)); // NOI18N   
  165.         jButton1.setText("发送");   
  166.         jButton1.addActionListener(new java.awt.event.ActionListener() {   
  167.             public void actionPerformed(java.awt.event.ActionEvent evt) {   
  168.                 jButton1ActionPerformed(evt);   
  169.             }   
  170.         });   
  171.         jList1.setModel(new javax.swing.AbstractListModel() {   
  172.    private static final long serialVersionUID = 1L;   
  173.    String[] strings = { "Item 1""Item 2""Item 3""Item 4""Item 5" };   
  174.             public int getSize() { return strings.length; }   
  175.             public Object getElementAt(int i) { return strings[i]; }   
  176.         });   
  177.         jScrollPane2.setViewportView(jList1);   
  178.         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());   
  179.         getContentPane().setLayout(layout);   
  180.         layout.setHorizontalGroup(   
  181.             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  182.             .addGroup(layout.createSequentialGroup()   
  183.                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  184.                     .addGroup(layout.createSequentialGroup()   
  185.                         .addGap(565656)   
  186.                         .addComponent(jLabel1)   
  187.                         .addGap(181818)   
  188.                         .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE))   
  189.                     .addGroup(layout.createSequentialGroup()   
  190.                         .addGap(262626)   
  191.                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  192.                             .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 440, javax.swing.GroupLayout.PREFERRED_SIZE)   
  193.                             .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 440, javax.swing.GroupLayout.PREFERRED_SIZE))   
  194.                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))   
  195.                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  196.                     .addGroup(layout.createSequentialGroup()   
  197.                         .addGap(262626)   
  198.                         .addComponent(jLabel2))   
  199.                     .addGroup(layout.createSequentialGroup()   
  200.                         .addGap(181818)   
  201.                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  202.                             .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)   
  203.                             .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE))))   
  204.                 .addContainerGap(24, Short.MAX_VALUE))   
  205.         );   
  206.         layout.setVerticalGroup(   
  207.             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)   
  208.             .addGroup(layout.createSequentialGroup()   
  209.                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)   
  210.                     .addGroup(layout.createSequentialGroup()   
  211.                         .addContainerGap()   
  212.                         .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE))   
  213.                     .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()   
  214.                         .addGap(444444)   
  215.                         .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)   
  216.                             .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)   
  217.                             .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))   
  218.                 .addGap(181818)   
  219.                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)   
  220.                     .addComponent(jScrollPane2)   
  221.                     .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 402, Short.MAX_VALUE))   
  222.                 .addGap(181818)   
  223.                 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)   
  224.                     .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)   
  225.                     .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE))   
  226.                 .addGap(393939))   
  227.         );   
  228.         pack();   
  229.     }   
  230.     private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {   
  231.            
  232.     }   
  233.     public void run() {   
  234.   System.out.println("My IP is"  
  235.     + socket.getInetAddress().getHostAddress());   
  236.   
  237.   while (flag) {   
  238.    try {   
  239.     in = new DataInputStream(socket.getInputStream());   
  240.     if (vectorIPtemp.size() != 0) {   
  241.      vectorIPtemp.removeAllElements();   
  242.     }   
  243.     boolean isIPStr = false;   
  244.     String message = in.readUTF(); // 从服务器发过来的信息   
  245.     System.out.println("从服务器获取的信息:" + message);   
  246.     // 进行匹配看是否有ip地址   
  247.     Pattern p;   
  248.     Matcher m;   
  249.     p = Pattern   
  250.       .compile("add[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}");   
  251.     m = p.matcher(message); // 将信息进行匹配。   
  252.     while (m.find()) {   
  253.      isIPStr = true// 说明是IP字符串。   
  254.      String message2 = m.group(); // 取得类似add222.17.110.117的地址。   
  255.      // 判断是否只有发送地址而已   
  256.      // String isOnlyIP=message.substring(message2.length());   
  257.      // if(!isOnlyIP.equals("")){   
  258.      // setMessage(isOnlyIP); //输出到textArea   
  259.      // }   
  260.      // 判断vectorIP中是否已存在该IP了。   
  261.      String IP = message2.substring(3);   
  262.      vectorIPtemp.addElement(IP);   
  263.      /** 由于一下只能判断增加去掉一样的IP的情况,故舍弃 */  
  264.      // boolean isExist=false;   
  265.      // if(vectorIP!=null){   
  266.      // for(int i=0;i<vectorIP.size();i++){   
  267.      // if((vectorIP.get(i).equals(IP))){   
  268.      // //如果不一样,则继续遍历。如果一样,说明存在改变isExist的值。   
  269.      // isExist=true ;   
  270.      // break; //遍历时,存在就退出。 杯具:第一次是自己,存在。而第二个不存在了,且不判断;故出错。   
  271.      // }   
  272.      // }   
  273.      // }   
  274.      // if(isExist==false){ //不存在就添加   
  275.      // vectorIP.addElement(IP);   
  276.      // }   
  277.      vectorIP.removeAllElements();// 先清空,再重新加载。   
  278.     }   
  279.   
  280.     // 如果执行了 while 里面的代码,则说明传过来的信息是做IP处理的。   
  281.     if (isIPStr == false) {   
  282.      setMessage(message);   
  283.     } else {   
  284.      vectorIP = (Vector<String>) vectorIPtemp.clone(); // 重新赋值给vectorIP   
  285.     }   
  286.   
  287.    } catch (IOException e) {   
  288.     serverClose = true// 服务器可能在有客户端存在的时候关闭,此时,客户端输入流会出错,刚执行此处   
  289.     setMessage("服务器关闭了!");   
  290.     flag = false;// 跳出循环   
  291.    }   
  292.   }   
  293.  }   
  294.   
  295.  private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {   
  296.   //    
  297.  }   
  298.   
  299.  private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {   
  300.   //    
  301.  }   
  302.      
  303.     public static void main(String args[]) {   
  304.           new MyJrame2().setVisible(true);        
  305.     }   
  306.     private javax.swing.JButton jButton1;   
  307.     private javax.swing.JLabel jLabel1;   
  308.     private javax.swing.JLabel jLabel2;   
  309.     private javax.swing.JList jList1;   
  310.     private javax.swing.JScrollPane jScrollPane1;   
  311.     private javax.swing.JScrollPane jScrollPane2;   
  312.     private javax.swing.JTextArea jTextArea1;   
  313.     private javax.swing.JTextField jTextField1;   
  314.     private javax.swing.JTextField jTextField2;   
  315. }   
  316.   

 
==================

有个很明显的漏洞可以修改在线IP。不过也有个很好的解决方法,那就是在客户端先对信息进行匹配处理。

最后张图:

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值