这是前段时间写的一个局域网多对多聊天系统,使用socket编程和TCP/IP协议进行数据传输。总体就两个部分,一个是客户端,还有一个是服务器端。其实这个系统编写起来还是很容易的。我这个小程序:
1、有一个登陆界面;
2、登陆之后进入聊天界面后会有一个服务器的欢迎语句。
在这里给出程序的源代码。
- 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();
- }
- }
- }
- }
- }
- <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();
- }
- }
- </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();
- }
- }
- }
- }
- }