socket编程——局域网聊天

2/10/2017来源:ASP.NET技巧人气:1108

 这是前段时间写的一个局域网多对多聊天系统,使用socket编程和TCP/ip协议进行数据传输。总体就两个部分,一个是客户端,还有一个是服务器端。其实这个系统编写起来还是很容易的。我这个小程序:

1、有一个登陆界面;

2、登陆之后进入聊天界面后会有一个服务器的欢迎语句。

在这里给出程序的源代码。

[java] view plain copy  PRint?在CODE上查看代码片派生到我的代码片 package org.zsl.server;      //服务器部分   import java.io.DataInputStream;      import java.io.DataOutputStream;   import java.io.EOFException;   import java.io.IOException;   import java.net.BindException;   import java.net.ServerSocket;   import java.net.Socket;   import java.util.ArrayList;   import java.util.Date;   import java.util.List;   /*   * ChatServer类  服务器   *  main()          启动程序入口   *  start1()        启动服务器,无线循环等待客户端   *    * ServerThread类            实现了Runnable接口    *  ServerThread(Socket s)  构造方法   *  send()                  发送数据给客户端   *  run()                   覆写方法,接收数据并发送给所有的客户端    * */      public class ChatServer {          private static boolean isRun = false;   //标识符          private ServerSocket serverSocket = null;       //服务器              private Socket client = null;                     private String name = null;              List<ServerThread> st = new ArrayList<ServerThread>();      //st集合用来装产生的服务器线程              public static void main(String[] args) {    //启动方法                      System.out.println("服务器启动!");           new ChatServer().start1();                  }              private void start1() {              try {               serverSocket = new ServerSocket(8888);      //实例化服务器,开启端口               isRun = true;                               //改变标识符           } catch (BindException e) {               System.out.println("端口使用中");               System.exit(0);           } catch (IOException e) {               e.printStackTrace();           }              try {                  while (isRun) {         //无限循环                      client = serverSocket.accept();     //等待客户端连接,阻塞                                      ServerThread serverThread = new ServerThread(client);   //一个客户端连接产生了一个服务器的线程                                                                            st.add(serverThread);                   //将线程加入结合                                      name = serverThread.dis.readUTF();                                      serverThread.setName(name);                                      new Thread(serverThread).start();       //启动线程                                      for (int i = 0; i < st.size(); i++) {    //遍历所有的线程                                              ServerThread temp = st.get(i);                                              temp.send("<服务器> 欢迎 "+this.name+" 进入聊天室!\n"); //向所有的线程发送信息                   }                                                         // dis.close();               }           } catch (IOException e) {               e.printStackTrace();           } finally {               try {                   serverSocket.close();       //关闭服务器               } catch (IOException e) {                   e.printStackTrace();               }           }       }          class ServerThread implements Runnable {              private Socket client;          //定义客户端                      private DataInputStream dis = null;         //定义输入流                      private DataOutputStream dos = null;        //定义输出流                      private boolean bConnected = false;         //定义标志位                      private boolean flag = true;                      private String name = null;     //定义用户姓名                      public String getName() {               return name;           }              public void setName(String name) {               this.name = name;           }              public ServerThread(Socket s) {               this.client = s;                              try {                   dis = new DataInputStream(s.getInputStream());      //实例化接收客户端的信息的对象                                      dos = new DataOutputStream(s.getOutputStream());    //实例化向客户端发送信息对象                                      bConnected = true;                                  } catch (IOException e) {                   e.printStackTrace();               }              }              public void send(String str) {      //发送信息的方法               try {                   dos.writeUTF(str);               } catch (IOException e) {                   st.remove(this);                  }           }              @Override           public void run() {                  try {                                      while (bConnected) {                                              String str = dis.readUTF();                                              for (int i = 0; i < st.size(); i++) {    //遍历所有的线程                                                      ServerThread temp = st.get(i);                                                      temp.send("<"+this.name+"  "+new Date()+">\n"+"  "+str);  //向所有的线程发送信息                       }                                          }               } catch (EOFException e) {                   System.out.println("client closed");               } catch (IOException e) {                   e.printStackTrace();               } finally {                   try {                       if (client != null) {                           client.close();                           client = null;                       }                       if (dis != null)                           dis.close();                       if (dos != null)                           dos.close();                   } catch (IOException e1) {                       e1.printStackTrace();                   }                  }              }          }   }   [java] view plain copy  print?在CODE上查看代码片派生到我的代码片 <pre code_snippet_id="137770" snippet_file_name="blog_20140101_2_5626823" name="code" class="java">package org.zsl.client;         import java.awt.Toolkit;   import java.awt.event.ActionEvent;   import java.awt.event.ActionListener;   import java.awt.event.WindowAdapter;   import java.awt.event.WindowEvent;      import javax.swing.JButton;   import javax.swing.JFrame;   import javax.swing.JLabel;   import javax.swing.JTextField;      //登陆界面   public class Register {       private JFrame frame = new JFrame("聊天系统登陆界面");              private JLabel lab = new JLabel("请输入姓名:",JLabel.CENTER);              private JTextField name = new JTextField();              private JButton submit=new JButton("登陆");              private JButton reset=new JButton("重置");              private String c_name = null;              public String getName(){    //取得用户注册姓名           return c_name;       }              public Register(){           submit.addActionListener(new ActionListener(){      //采用匿名内部类,注册submit的事件监听               public void actionPerformed(ActionEvent arg0){                   if(arg0.getSource()==submit){               //判断触发源是否是提交按钮                                          c_name=name.getText();                                              new ChatClient(c_name); //将c_name传递到了ChatClient中                                              frame.dispose();    //关闭本窗口                   }               }           });           reset.addActionListener(new ActionListener(){//注册reset的时间监听               public void actionPerformed(ActionEvent arg1){                   if(arg1.getSource()==reset){//这个按钮没有反应                       name.setText("");                   }               }           });           frame.addWindowListener(new WindowAdapter(){               public void windowClosing(WindowEvent arg0){                   System.exit(1);               }           });                                 frame.setLayout(null);                      lab.setBounds(25, 50, 100, 50);           name.setBounds(135, 60, 150, 30);           submit.setBounds(75, 120, 80, 30);           reset.setBounds(190, 120, 80, 30);                                 frame.add(lab);           frame.add(name);           frame.add(submit);           frame.add(reset);                                            int width = 350;           int high = 240;           int w = (Toolkit.getDefaultToolkit().getScreenSize().width - width) / 2;           int h = (Toolkit.getDefaultToolkit().getScreenSize().height - high) / 2;                      frame.setSize(width, high);                      frame.setLocation(w, h);                      frame.setVisible(true);       }              public static void main(String[] args) {           new Register();       }   }  



[java] view
 plain copy


 print?在CODE上查看代码片派生到我的代码片



</pre><pre code_snippet_id="137770" snippet_file_name="blog_20140101_4_5943251" name="code" class="java"><pre code_snippet_id="137770" snippet_file_name="blog_20140101_4_5943251" name="code" class="java">package org.zsl.client;  
  
//客户端部分  
import java.awt.Frame;  
import java.awt.TextArea;  
import java.awt.TextField;  
import java.awt.Toolkit;  
import java.awt.event.ActionEvent;  
import java.awt.event.ActionListener;  
import java.awt.event.WindowAdapter;  
import java.awt.event.WindowEvent;  
import java.io.DataInputStream;  
import java.io.DataOutputStream;  
import java.io.EOFException;  
import java.io.IOException;  
import java.net.Socket;  
import java.net.SocketException;  
import java.net.UnknownHostException;  
  
import javax.swing.JButton;  
import javax.swing.JPanel;  
  
public class ChatClient extends Frame {  
  
    Socket socket = null;  
  
    TextField inputChat = new TextField(); // 定义文本框用来输入数据  
  
    TextArea showChat = new TextArea(); // 展示数据的地方  
  
    JButton submit = new JButton("发送");  
  
    JPanel pan = new JPanel();  
  
    DataInputStream dis = null; // 接收流  
  
    DataOutputStream dos = null; // 输出流  
  
    private String c_name = null;  
  
    private static boolean isRun = false;  
  
    private boolean flag = true; // 让c_name的传递只有一次  
  
    public ChatClient() {  
    }  
  
    public static void main(String[] args) {  
        new ChatClient().launchFrame();  
    }  
  
    public ChatClient(String name) {  
        this.c_name = name;  
        this.launchFrame();  
    }  
  
    public void launchFrame() { // Swing 界面  
        this.setTitle("局域网聊天系统");  
  
        int width = 510;  
        int high = 360;  
  
        this.setLayout(null);  
        this.setSize(width, high);  
  
        showChat.setBounds(5, 5, 490, 295);  
        pan.setBounds(5, 305, 490, 45);  
  
        pan.setLayout(null);  
        inputChat.setBounds(5, 5, 400, 40);  
        submit.setBounds(405, 5, 95, 40);  
  
        // 居中地位  
        int w = (Toolkit.getDefaultToolkit().getScreenSize().width - width) / 2;  
        int h = (Toolkit.getDefaultToolkit().getScreenSize().height - high) / 2;  
  
        pan.add(inputChat);  
        pan.add(submit);  
  
        this.add(showChat);  
        this.add(pan);  
  
        this.setLocation(w, h);  
  
        this.setVisible(true);  
  
        addWindowListener(new WindowAdapter() {  
            @Override  
            public void windowClosing(WindowEvent e) {  
                disconnect();  
                System.exit(0);  
            }  
        });  
          
        inputChat.addActionListener(new TextFieldListener()); // 输入窗口中添加监听  
        submit.addActionListener(new TextFieldListener()); // 输入窗口中添加监听  
  
        connectToServer(); // 连接服务器  
  
        Thread clientThread = new Thread(new ClientThread());  
  
        clientThread.start(); // 启动客户端线程  
    }  
  
    private void connectToServer() {  
        try {  
            socket = new Socket("125.221.225.105", 8888);  
  
            dis = new DataInputStream(socket.getInputStream());  
  
            dos = new DataOutputStream(socket.getOutputStream());  
            isRun = true;  
        } catch (UnknownHostException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public void disconnect() { // 如果没连接上服务器则关闭输入输出流和客户端套接字  
  
        // 关闭各种流之前必须先关闭接受线程  
        try {  
            if (dos != null) {  
                dos.close();  
            }  
            if (dis != null) {  
                dis.close();  
            }  
            if (socket != null) {  
                socket.close();  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
  
    private class ClientThread implements Runnable {  
  
        @Override  
        public void run() {  
  
            try {  
  
                if (flag) { // 启动客户端只传递一次姓名  
                    dos.writeUTF(c_name);  
                    flag = false;  
                }  
  
                while (isRun) { // 无线循环  
  
                    String str = dis.readUTF(); // 取得服务器端发送的消息  
  
                    // System.out.println(str);  
                    // showChat中的部分由以前的 和 现在的组成  
                    showChat.setText(showChat.getText() + str + '\n'); // 在showChat中显示  
  
                }  
            } catch (SocketException e) {  
                System.out.println("bye");  
            } catch (EOFException e) {  
  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
  
    }  
  
    private class TextFieldListener implements ActionListener {  
  
        @Override  
        public void actionPerformed(ActionEvent e) {  
            String s = inputChat.getText().trim();  
            if (e.getSource() == submit) {  
                if(!("".equals(s))){  
                    // showChat.setText(s);  
                    inputChat.setText("");  
                    try {  
                        dos.writeUTF(s);  
                        dos.flush();  
                        // dos.close();  
                    } catch (IOException e1) {  
                        e1.printStackTrace();  
                    }  
                }  
            } else {  
                // showChat.setText(s);  
                inputChat.setText("");  
                try {  
                    dos.writeUTF(s);  
                    dos.flush();  
                    // dos.close();  
                } catch (IOException e1) {  
                    e1.printStackTrace();  
                }  
            }  
  
        }  
  
    }  
  
}