简单的聊天程序,主要用到的是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 + '\n');

    }

   } catch (SocketException e){

    System.out.println("退出了,bye!");

   } catch (IOException e) {  

    e.printStackTrace();

   }

  }

}

}

 

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

如果没看懂可以去我博客

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

转载于:https://www.cnblogs.com/huidaoli/p/3252924.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值