• 简单的聊天程序,主要用到的是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

  • 相关阅读:
    layer 刷新某个页面
    C# Server.MapPath的使用方法
    .net mvc + layui做图片上传(二)—— 使用流上传和下载图片
    ASP.NET MVC4.0 后台获取不大前台传来的file
    安卓手机修改host
    mvc 页面 去掉转义字符
    educoder数据库实训课程-shell语句总结
    python selenium实现自动操作chrome的某网站数据清洗【此篇为jupyter notebook直接导出.md】
    LeetCode_27移除元素【数组】
    LeetCode_26 删除排序数组中的重复项【数组】
  • 原文地址:https://www.cnblogs.com/huidaoli/p/3252924.html
Copyright © 2020-2023  润新知