zoukankan      html  css  js  c++  java
  • 简单的聊天程序,主要用到的是Socket

    服务端:

      1 import java.io.*;
      2 
      3 import java.net.*;
      4 
      5 import java.util.*;
      6 
      7 public class ChatServer {
      8 
      9 boolean stat = false;
     10 
     11 ServerSocket ss = null;
     12 
     13 List<Client> clients = new ArrayList<Client>();//用于存客户端
     14 
     15 public static void main(String[] args) {
     16 
     17   new ChatServer().start();
     18 
     19 }
     20 
     21 public void start(){
     22 
     23   try {
     24 
     25    ss = new ServerSocket(8888);
     26 
     27    stat = true;
     28 
     29   } catch(BindException e){  //Sever端已经运行,当重复运行时抛异常
     30 
     31    System.out.println("端口正在使用中。。。。");
     32 
     33    System.out.println("请关掉相关程序并重新运行服务器!"); //还会抛别的异常,所以直接关闭窗口
     34 
     35    System.exit(0);
     36 
     37   } catch(IOException e) {
     38 
     39    e.printStackTrace();
     40 
     41   }
     42 
     43   try{
     44 
     45    while(stat){
     46 
     47     Socket s = ss.accept();
     48 
     49 System.out.println("a client connected!" );  //测试语句写在最左边,以后没用可以删除或注掉
     50 
     51     Client c = new Client(s);    //每建立一个客户端,就new一个客户端对象,启动一个线程
     52 
     53     new Thread(c).start();
     54 
     55     clients.add(c);  //勿忘写,将每个客户端加入到容器里
     56 
     57    }
     58 
     59   } catch (IOException e) {
     60 
     61    e.printStackTrace();
     62 
     63   } finally {
     64 
     65    try {
     66 
     67     ss.close();
     68 
     69    } catch (IOException e) {
     70 
     71     e.printStackTrace();
     72 
     73    }
     74 
     75   }
     76 
     77 }
     78 
     79 class Client implements Runnable {
     80 
     81   private Socket s;
     82 
     83   private DataInputStream dis;
     84 
     85   private DataOutputStream dos;
     86 
     87   private boolean cont = false;
     88 
     89   public Client(Socket s){
     90 
     91    this.s = s; 
     92 
     93    try {
     94 
     95     dis = new DataInputStream(s.getInputStream());//初始化
     96 
     97     dos = new DataOutputStream(s.getOutputStream());
     98 
     99     cont = true;
    100 
    101    } catch (IOException e) {
    102 
    103     e.printStackTrace();
    104 
    105    }
    106 
    107   }
    108 
    109   public void send(String str){  //用于发送给客户端
    110 
    111    try {
    112 
    113     dos.writeUTF(str);
    114 
    115    } catch (IOException e) {
    116 
    117     clients.remove(this);  //移除那个退出的对象
    118 
    119     System.out.println("一个客户退出了");
    120 
    121     //e.printStackTrace();
    122 
    123    }
    124 
    125   }
    126 
    127   public void run() {
    128 
    129    try{
    130 
    131     while(cont){
    132 
    133      String str = dis.readUTF(); //阻塞式方法
    134 
    135 System.out.println(str);
    136 
    137      for(int i=0; i<clients.size(); i++){
    138 
    139       Client c = clients.get(i);  //取客户端
    140 
    141       c.send(str); 
    142 
    143      }
    144 
    145      /*     另外两种方法,但不适用,它会锁定服务端
    146 
    147      for(Iterator<Client> it = clients.iterator(); it.hasNext();){
    148 
    149       Client c = it.next();
    150 
    151       c.send(str);
    152 
    153      }
    154 
    155      Iterator<Client> it = clients.iterator();
    156 
    157      while(it.hasNext()){
    158 
    159       Client c = it.next();
    160 
    161       c.send(str);
    162 
    163      }
    164 
    165      */
    166 
    167     }
    168 
    169    } catch (EOFException e){   //readUTF()阻塞式方法,所以关闭客户端会抛异常
    170 
    171     System.out.println("Client closed!");
    172 
    173    } catch (IOException e) {
    174 
    175     e.printStackTrace();
    176 
    177    } finally {
    178 
    179     try {
    180 
    181      if(dis != null) dis.close();
    182 
    183      if(dos != null) dos.close();
    184 
    185      if(s != null) {
    186 
    187       s.close();
    188 
    189       s = null;//更严格的方法,等于空就没人去用了,垃圾收集器就回收走
    190 
    191      }
    192 
    193     } catch (IOException e) {
    194 
    195      e.printStackTrace();
    196 
    197     }
    198 
    199    }
    200 
    201   }
    202 
    203 }
    204 
    205 }

    客户端:

    import java.awt.*;
    
    import java.awt.event.*;
    
    import java.io.*;
    
    import java.net.*;
    
    public class ChatClient extends Frame {
    
    Socket s = null;
    
    DataOutputStream dos = null;
    
    DataInputStream dis = null;
    
    private boolean cont = false;
    
    TextField tfTxt = new TextField();
    
    TextArea taContent = new TextArea();
    
    Thread tRecv = new Thread(new RecvThread());
    
    public static void main(String[] args) {
    
      new ChatClient().launchFrame();
    
    }
    
    public void launchFrame() {
    
      setLocation(400, 300);
    
      this.setSize(300, 300);
    
      add(tfTxt,BorderLayout.SOUTH);
    
      add(taContent,BorderLayout.NORTH);
    
      pack(); //包在一起,去掉中间空着的
    
      this.addWindowListener(new WindowAdapter(){
    
       public void windowClosing(WindowEvent e){
    
        disconnect();
    
        System.exit(0);
    
       }
    
      });
    
      tfTxt.addActionListener(new TfListent());
    
      setVisible(true);
    
      connect();
    
      tRecv.start();   //启动线程
    
    }
    
    public void connect(){
    
      try {
    
       s = new Socket("127.0.0.1",8888);//注意不要定义成Socket s,这就成了局部变量而不是成员变量了
    
    System.out.println("connected!");
    
       dos = new DataOutputStream(s.getOutputStream());
    
       dis = new DataInputStream(s.getInputStream());
    
       cont = true;
    
      } catch (UnknownHostException e) {
    
       e.printStackTrace();
    
      } catch (IOException e) {
    
       e.printStackTrace();
    
      }
    
    }
    
    public void disconnect(){
    
      try {
    
       dos.close();
    
       dis.close();
    
       s.close();
    
      } catch (IOException e) {
    
       e.printStackTrace();
    
      }
    
      /*//无法解决readUTF阻塞式方法
    
      try {
    
       cont = false;  //关闭线程
    
       tRecv.join();  //合并线程,彻底让他停止
    
      } catch (InterruptedException  e) {
    
       e.printStackTrace();
    
      } finally {
    
       try {
    
        dos.close(); //线程停止之后才能关流,不然抛SocketException异常
    
        dis.close();
    
        s.close();
    
       } catch (IOException e) {
    
        e.printStackTrace();
    
       }
    
      }
    
      */
    
    }
    
    private class TfListent implements ActionListener {
    
      public void actionPerformed(ActionEvent e) {
    
       String str = tfTxt.getText().trim();
    
       tfTxt.setText("");
    
       try {
    
        dos.writeUTF(str);
    
        dos.flush();
    
       } catch (IOException e1) {
    
        e1.printStackTrace();
    
       }
    
      }
    
    }
    
    private class RecvThread implements Runnable{
    
      public void run() {
    
       try {
    
        while(cont){
    
         String str = dis.readUTF();
    
         taContent.setText(taContent.getText() + str + '
    ');
    
        }
    
       } catch (SocketException e){
    
        System.out.println("退出了,bye!");
    
       } catch (IOException e) {  
    
        e.printStackTrace();
    
       }
    
      }
    
    }
    
    }

    简单的聊天程序,主要用到的是Socket,线程以及流

    如果没看懂可以去我博客

    http://www.cnblogs.com/huidaoli/p/3252924.html

  • 相关阅读:
    HDU 5642 King's Order 动态规划
    HDU 5640 King's Cake GCD
    HDU 5641 King's Phone 模拟
    HDU 5299 Circles Game 博弈论 暴力
    HDU 5294 Tricks Device 网络流 最短路
    HDU 5289 Assignment rmq
    HDU 5288 OO’s Sequence 水题
    星际争霸 虚空之遗 人族5BB 操作流程
    Codeforces Beta Round #3 D. Least Cost Bracket Sequence 优先队列
    Codeforces Beta Round #3 C. Tic-tac-toe 模拟题
  • 原文地址:https://www.cnblogs.com/huidaoli/p/3252924.html
Copyright © 2011-2022 走看看