黑马程序员技术交流社区

标题: javase练习,简单多客户端聊天 [打印本页]

作者: 一叶障目    时间: 2014-11-27 14:39
标题: javase练习,简单多客户端聊天
  1. package cn.seven.client;

  2. import java.awt.BorderLayout;
  3. import java.awt.Frame;
  4. import java.awt.TextArea;
  5. import java.awt.TextField;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.ActionListener;
  8. import java.awt.event.WindowAdapter;
  9. import java.awt.event.WindowEvent;
  10. import java.io.DataInputStream;
  11. import java.io.DataOutputStream;
  12. import java.io.IOException;
  13. import java.net.ConnectException;
  14. import java.net.Socket;
  15. import java.net.UnknownHostException;

  16. public class ChatClient extends Frame{
  17.         private TextField field=new TextField();
  18.         private TextArea area=new TextArea();
  19.         private Socket s=null;
  20.         private DataOutputStream dips=null;
  21.         private DataInputStream dops=null;
  22.         private boolean connect=false;
  23.         public static void main(String[] args) {
  24.                 new ChatClient().launch();
  25.         }
  26.         public void launch(){
  27.                 this.setBounds(300, 200,300,200);
  28.                 this.addWindowListener(new WindowAdapter(){
  29.                         public void windowClosing(WindowEvent e) {
  30.                                 System.exit(0);
  31.                         }
  32.                 });
  33.                 this.add(field,BorderLayout.SOUTH);
  34.                 this.add(area,BorderLayout.NORTH);
  35.                 pack();
  36.                 area.setEditable(false);
  37.                 field.addActionListener(new TextListener());
  38.                 this.setVisible(true);
  39.                 connect();
  40.                 new Thread(new Receive()).start();
  41.         }
  42.         private class Receive implements Runnable{
  43.                 public void run(){
  44.                         try {
  45.                                 while(connect){
  46.                                         String str=dops.readUTF();
  47.                                         area.append(str+"\r\n");
  48.                                 }
  49.                         } catch (IOException e) {
  50.                                 // TODO Auto-generated catch block
  51.                                 e.printStackTrace();
  52.                         }
  53.                 }
  54.         }
  55.         private void connect() {
  56.                 try {
  57.                         s=new Socket("localhost",8888);
  58.                         connect=true;
  59.                         dips=new DataOutputStream(s.getOutputStream());
  60.                         dops=new DataInputStream(s.getInputStream());
  61.                 } catch (ConnectException e) {
  62.                         System.out.println("服务器未开启");
  63.                         System.exit(0);
  64.                 } catch (UnknownHostException e) {
  65.                         e.printStackTrace();
  66.                 } catch (IOException e){
  67.                         e.printStackTrace();
  68.                 }
  69.         }
  70.         private class TextListener implements ActionListener{

  71.                 public void actionPerformed(ActionEvent e) {
  72.                         String str=null;
  73.                         str=field.getText();
  74.                         try {
  75.                                         if(str!=null&&!str.isEmpty()){
  76.                                                 //area.append(str+"\r\n");
  77.                                                 dips.writeUTF(str);
  78.                                                 dips.flush();
  79.                                                 field.setText("");
  80.                                         }
  81.                                 } catch (IOException e1) {
  82.                                         // TODO Auto-generated catch block
  83.                                         e1.printStackTrace();
  84.                                 }
  85.                         }
  86.                        
  87.                 }
  88. }
复制代码
  1. package cn.seven.sever;

  2. import java.io.DataInputStream;
  3. import java.io.DataOutputStream;
  4. import java.io.IOException;
  5. import java.net.BindException;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. import java.net.SocketException;
  9. import java.util.ArrayList;
  10. import java.util.List;

  11. public class ChatServer {
  12.         private static ServerSocket ss;
  13.         private static List<ClientRun> clients=new ArrayList<ClientRun>();
  14.         public static void main(String[] args) {
  15.                 boolean start=false;
  16.                 try {
  17.                         ss = new ServerSocket(8888);
  18.                         start=true;
  19.                         while(start){
  20.                                 Socket s=ss.accept();
  21.                                 String ip=s.getInetAddress().getHostName()+"::::::"+s.getPort();
  22.                         System.out.println(ip+":connect");
  23.                         ClientRun c=new ClientRun(s);
  24.                                 new Thread(c).start();
  25.                                 clients.add(c);
  26.                         }
  27.                 }catch (BindException e) {
  28.                         System.out.println("服务器已经开启,不要重复开启");
  29.                         System.exit(0);
  30.                 } catch (IOException e) {
  31.                         e.printStackTrace();
  32.                 }
  33.         }
  34.         static class ClientRun implements Runnable
  35.         {
  36.                 private Socket s;
  37.                 private DataInputStream dips;
  38.                 private DataOutputStream dops;
  39.                 ClientRun(Socket s)
  40.                 {
  41.                         this.s=s;
  42.                 }
  43.                 public void send(String str){
  44.                         try {
  45.                                 dops=new DataOutputStream(s.getOutputStream());
  46.                                 dops.writeUTF(str);
  47.                         } catch (IOException e) {
  48.                                 clients.remove(this);
  49.                                 System.out.println(s.getPort()+"已经退出");
  50.                         }
  51.                        
  52.                 }
  53.                 public void run() {
  54.                         boolean connect=true;
  55.                         int port=s.getPort();
  56.                         try {
  57.                                 while(connect){
  58.                                         dips=new DataInputStream(s.getInputStream());
  59.                                         String str=dips.readUTF();
  60.                                         System.out.println("["+port+"]"+str);
  61.                                         for(int x=0;x<clients.size();x++){
  62.                                                 clients.get(x).send(port+":"+str);
  63.                                         }
  64.                                 }
  65.                         } catch (SocketException e) {
  66.                                 System.out.println("a client of port "+port+" is unconnect");
  67.                         }catch (IOException e) {
  68.                                 e.printStackTrace();
  69.                         }finally{
  70.                                 if(dips!=null){
  71.                                         try {
  72.                                                 dips.close();
  73.                                         } catch (IOException e) {
  74.                                                 // TODO Auto-generated catch block
  75.                                                 e.printStackTrace();
  76.                                         }
  77.                                 }
  78.                                 if(s!=null){
  79.                                         try {
  80.                                                 s.close();
  81.                                         } catch (IOException e) {
  82.                                                 // TODO Auto-generated catch block
  83.                                                 e.printStackTrace();
  84.                                         }
  85.                                 }
  86.                         }
  87.                 }
  88.                
  89.         }
  90. }
复制代码



Chat2.zip

12.15 KB, 下载次数: 59


作者: ppStudent    时间: 2014-11-27 23:33
一句注释都不加的代码,这么差的阅读性,你要我怎么看,恩?
作者: 一叶障目    时间: 2014-11-28 10:11
ppStudent 发表于 2014-11-27 23:33
一句注释都不加的代码,这么差的阅读性,你要我怎么看,恩?

哦,抱歉,没注意这个问题,下次会注意的,请见谅:lol
作者: 桃华月禅    时间: 2014-11-28 10:27
我当初写的那个为什么技术分只有1分,,,UDP聊天和TCP聊天的差距吗?

过去写过的UDP的东东,好久不看我都快自己看不懂了...= =复习基础才到多线程...
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.net.*;
  4. import java.text.*;
  5. import java.util.*;

  6. class NewChattingFrameTest       
  7. {
  8.         public static void main(String[] args)throws Exception{
  9.                 DatagramSocket dsSend = new DatagramSocket();
  10.                 DatagramSocket dsReceive = new DatagramSocket(10000);

  11.                 new ChattingFrame(dsSend,dsReceive);
  12.         }
  13. }

  14. class ChattingFrame
  15. {
  16.         private Frame f;
  17.         private TextArea taSend,taReceive;
  18.         private Panel pSend,pReceive;
  19.         private Button b;
  20.         private DatagramSocket dsSend,dsReceive;

  21.         //这个窗体是为了传送接收信息的,构造时需要发送和接收数据的包
  22.         ChattingFrame(DatagramSocket dsSend,DatagramSocket dsReceive){
  23.                 this.dsSend = dsSend;
  24.                 this.dsReceive = dsReceive;
  25.                 init();

  26.                 Receive r = new Receive(dsReceive,taReceive);
  27.                 new Thread(r).start();
  28.         }

  29.         public void init(){
  30.                 f = new Frame("聊天程序");
  31.                
  32.                 f.setBounds(400,200,500,420);
  33.                 f.setLayout(new BorderLayout(10,10));

  34.                 //建立上下主面板
  35.                 pSend = new Panel();
  36.                 pSend.setPreferredSize(new Dimension(300,100));
  37.                 pReceive = new Panel();
  38.                 pReceive.setPreferredSize(new Dimension(300,300));
  39.                
  40.                 //布局下边的发送面板内的内容
  41.                 pSend.setLayout(new BorderLayout(10,10));
  42.                 taSend = new TextArea();
  43.                 taSend.setPreferredSize(new Dimension(250,60));
  44.                 b = new Button("发送");
  45.                 b.setPreferredSize(new Dimension(30,20));
  46.                 pSend.add(taSend,BorderLayout.CENTER);
  47.                 pSend.add(b,BorderLayout.EAST);

  48.                 //布局上边接收面板的内容
  49.                 pReceive.setLayout(new BorderLayout());
  50.                 taReceive = new TextArea();
  51.                 taReceive.setEditable(false);
  52.                 pReceive.add(taReceive);

  53.                 //把主面板添加进窗体内
  54.                 f.add(pSend,BorderLayout.SOUTH);
  55.                 f.add(pReceive,BorderLayout.CENTER);
  56.                
  57.                 myEvent();
  58.                 f.setVisible(true);
  59.         }

  60.         public void myEvent(){
  61.                 f.addWindowListener(new WindowAdapter(){
  62.                         public void windowClosing(WindowEvent e){
  63.                                 System.exit(0);
  64.                         }
  65.                 });

  66.                 //添加按钮监听,点击按钮发送信息
  67.                 b.addActionListener(new ActionListener(){
  68.                         public void actionPerformed(ActionEvent e){
  69.                                 new Thread(new Send(dsSend,taSend.getText())).start();                               
  70.                                 //System.out.println("清空内容前的长度"+taSend.getText().length());
  71.                                 taSend.setText("");
  72.                                 //System.out.println("清空内容后的长度"+taSend.getText().length());
  73.                         }
  74.                 });
  75.                
  76.                 //添加键盘监听,点击回车发送数据
  77.                 taSend.addKeyListener(new KeyAdapter(){
  78.                         public void keyPressed(KeyEvent e){
  79.                                 if(e.getKeyCode()==KeyEvent.VK_ENTER && !e.isControlDown()){
  80.                                         e.consume();
  81.                                         new Thread(new Send(dsSend,taSend.getText())).start();
  82.                                         //System.out.println("清空内容前的长度"+taSend.getText().length());
  83.                                         taSend.setText("");
  84.                                         //System.out.println("清空内容后的长度"+taSend.getText().length());
  85.                                 }
  86.                                 //if(taSend.getText()=="\r\n")
  87.                                         //taSend.setText("");
  88.                         }
  89.                 });
  90.         }
  91. }

  92. class Send implements Runnable
  93. {
  94.         private DatagramSocket ds;
  95.         private String taSend;
  96.        
  97.         //构造时需要接收要发送的数据和发送数据的包
  98.         Send(DatagramSocket ds,String taSend){
  99.                 this.ds = ds;
  100.                 this.taSend = taSend;
  101.         }

  102.         public void run(){
  103.                 try
  104.                 {
  105.                         if(taSend==null)
  106.                                 return;
  107.                         byte[] buf = taSend.getBytes();
  108.                         //System.out.println("Send类的taSend的长度:"+taSend.length());
  109.                         //System.out.println("buf的长度:"+buf.length);
  110.                        
  111.                         if(buf.length!=0){
  112.                                 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.23.12.86"),10000);//发送给指定IP
  113.                                 DatagramPacket owndp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);//发送给本机

  114.                                 ds.send(dp);
  115.                                 ds.send(owndp);
  116.                         }
  117.                         else
  118.                                 return;
  119.                 }
  120.                 catch (UnknownHostException e)
  121.                 {
  122.                         throw new RuntimeException("未知主机");
  123.                 }
  124.                 catch(Exception e)
  125.                 {
  126.                         throw new RuntimeException("IO异常");
  127.                 }
  128.         }
  129. }

  130. class Receive implements Runnable
  131. {
  132.         private DatagramSocket ds;
  133.         private TextArea taReceive;
  134.        
  135.         //构造时需要接收数据的包和输出接收数据的窗体组件TextArea
  136.         Receive(DatagramSocket ds,TextArea taReceive){
  137.                 this.ds = ds;
  138.                 this.taReceive = taReceive;
  139.         }

  140.         public void run(){
  141.                 //为实现边输入边接收数据的功能,接收程序必须一直执行,不能停止,所以定义无限循环
  142.                 while(true){
  143.                         try
  144.                         {
  145.                                 byte[] buf = new byte[1024];
  146.                                
  147.                                 DatagramPacket dp = new DatagramPacket(buf,buf.length);

  148.                                 ds.receive(dp);

  149.                                 int length = dp.getLength();
  150.                                 //接收的数据以字符串形式存储
  151.                                 String content = new String(dp.getData(),0,length);
  152.                                 //获取现在的时间以字符串形式存储
  153.                                 SimpleDateFormat sdf = new SimpleDateFormat("H:m:s");
  154.                                 String date = sdf.format(new Date());
  155.                                 //排列出要显示的信息样式保存在一个字符串当中
  156.                                 String textReceive = dp.getAddress().getHostName()+" "+date+" \r\n"+content+"\r\n\r\n";
  157.                                 //把定义好的字符串添加进taRecieve组件
  158.                                 taReceive.append(textReceive);
  159.                         }
  160.                         catch (Exception e)
  161.                         {
  162.                                 throw new RuntimeException("接收出现错误");
  163.                         }
  164.                 }
  165.         }
  166. }
复制代码


作者: l763631191    时间: 2014-11-28 10:40
哈哈 ,加注释是个好习惯~~毕竟代码不是只给自己看的~~
作者: 一叶障目    时间: 2014-11-28 15:55
ppStudent 发表于 2014-11-27 23:33
一句注释都不加的代码,这么差的阅读性,你要我怎么看,恩?

(⊙o⊙)哦。。。。知道了,第一次做这种练习,下次会改正的:handshake
作者: 一叶障目    时间: 2014-11-28 15:57
l763631191 发表于 2014-11-28 10:40
哈哈 ,加注释是个好习惯~~毕竟代码不是只给自己看的~~

嗯哪,是的,我是刚做好就发上来的,没顾虑注释什么的,不过感觉这个代码不长,而已很简单的应该读起来不难吧:lol。,。。。。下次会注意的




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2