Java socket 聊天室 4.0

该博客展示了如何使用Java实现一个简单的聊天室服务器和客户端。服务器端通过ServerSocket监听8888端口,接收多个客户端连接,每个连接创建一个线程处理通信。客户端连接到服务器,读取服务器发送的消息并在用户输入后发送回消息。程序实现了多用户并发聊天功能。
摘要由CSDN通过智能技术生成

 服务器代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class server extends JFrame implements ActionListener , KeyListener {
    public static void main(String[] arg){
        //构造界面
        new server();

    }
    //属性
    //文本域
    private final JTextArea jTextArea;
    //滚动条
    private final JScrollPane jScrollPane;
    //面板
    private final JPanel jPanel;
    //文本框
    private final JTextField jTextField;
    //发送文本按钮
    private final JButton jButtonText;

    //
    ServerSocket serverSocket;
    //线程池
    private static sThread[] sThreadList=new sThread[1024];
    private int[] nextList=new int[1024];
    private boolean[] isRun=new boolean[1024];
    private int last;
    private int head;

    //构造方法
    public server() {
        //初始化
        jTextArea = new JTextArea();
        //文本域默认不可编辑
        jTextArea.setEditable(false);
        jScrollPane = new JScrollPane(jTextArea);//将文本域添加到滚动条中
        jPanel = new JPanel();
        jTextField = new JTextField(30);
        jButtonText = new JButton("发送");
        //将文本框与按钮添加到面板中
        jPanel.add(jTextField);
        jPanel.add(jButtonText);

        //将滚动条与面板添加到窗体中
        this.add(jScrollPane, BorderLayout.CENTER);
        this.add(jPanel, BorderLayout.SOUTH);

        //标题
        this.setTitle("ZZ聊天室服务器 4.0");
        //大小
        this.setSize(500, 300);
        //位置
        this.setLocation(500, 200);
        //关闭窗口程序结束
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗体可见
        this.setVisible(true);

        //监听按钮
        jButtonText.addActionListener(this);
        //监听文本框
        jTextField.addKeyListener(this);

       try{
           //创建端口监听
           serverSocket = new ServerSocket(8888);
           //创建udp线程
           new QuoteServerThread().start();
           head=last =1;  //线程开始位置
           while(true){
               sThreadList[last]=new sThread(serverSocket.accept(),last);
               new Thread(sThreadList[last]).start();
               isRun[last]=true;
               if(nextList[last]!=0) last =nextList[last];
               else last =nextList[last]= last +1;

           }
       }catch (IOException e){
           e.printStackTrace();
       }



    }
    class sThread implements Runnable {
        Socket socket;
        int num;
        BufferedReader in;

        public sThread(Socket socket,int num) {
            this.socket = socket;
            this.num=num;
            //由socket获得io对象
            try {
                in = new BufferedReader(new
                        InputStreamReader(socket.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void run() {
            try {

                //通知有人加入
                SendTextToSockets(num,"欢迎新用户:"+num+"加入");
                SendTextToSocket(new PrintWriter(sThreadList[num].socket.getOutputStream()),"欢迎您加入,您的号码是:"+num);
                jTextArea.append("有新用户加入,代号:" + num + "\n"); //在文本域中显示
                for (String read_line = in.readLine(); !read_line.equals("bye"); read_line = in.readLine()) {
                    String text;
                    //读入字符串输出到Client 显示
                    if(read_line.length()>2&&read_line.charAt(2)==read_line.charAt(1) && read_line.charAt(2)==':') {
                        text="用户" + num + "私聊说:" + read_line;
                        SendTextToSocket(
                                new PrintWriter(sThreadList[read_line.charAt(0)-'0'].socket.getOutputStream()), text);

                    }
                    else {
                        text="用户" + num + "说:" + read_line;
                        SendTextToSockets(num, text);
                    }
                    jTextArea.append(text+System.lineSeparator());
                }
                //线程释放
                SendTextToSockets(0,"用户:"+num+"已下线");
                isRun[num]=false;
                if(head==num) head=nextList[num];
                nextList[num]=last;
                last=num;
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    //行为

    private void SendTextToSockets(int num,String Text) {
        PrintWriter out;
        for(int i=head;isRun[i];i=nextList[i]) {
            if(i==num)continue;
            try {
                out = new PrintWriter(sThreadList[i].socket.getOutputStream());
                out.println(Text);

                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //清空文本框
        jTextField.setText("");
    }
    private void SendTextToSocket( PrintWriter out,String s){
        try{
            out.println(s);
            out.flush();
            //清空文本框
            jTextField.setText("");
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        jTextArea.append(jTextField.getText()+"\n");
        SendTextToSockets(0,"服务器说:"+ jTextField.getText());

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        //按下回车
        if(e.getKeyCode()==KeyEvent.VK_ENTER){
            jTextArea.append(jTextField.getText()+"\n");
            SendTextToSockets(0,"服务器说:"+ jTextField.getText());
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

}

客户端代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;

public class client extends JFrame implements ActionListener, KeyListener {
    public static void main(String[] arg){
        //构造界面
        new client();
    }
    //属性
    //文本域
    private final JTextArea jta;
    //滚动条
    private final JScrollPane jScrollPane;
    //面板
    private final JPanel jPanel;
    //文本框
    private final JTextField jTextField;
    //按钮
    private final JButton jButtonText;
    //发送文件按钮
    private final JButton jButtonFile;

    //输出流
    private PrintWriter out;
    //构造方法
    public client() {
        //初始化
        jta=new JTextArea();
        //文本域默认不可编辑
        jta.setEditable(false);
        jScrollPane =new JScrollPane(jta);//将文本域添加到滚动条中
        jPanel =new JPanel();
        jTextField =new JTextField(30);
        jButtonText =new JButton("发送");
        jButtonFile = new JButton("文件");
        //将文本框与按钮添加到面板中
        jPanel.add(jTextField);
        jPanel.add(jButtonText);
        jPanel.add(jButtonFile);

        //将滚动条与面板添加到窗体中
        this.add(jScrollPane, BorderLayout.CENTER);
        this.add(jPanel,BorderLayout.SOUTH);

        //标题
        this.setTitle("ZZ聊天室客户端 4.0");
        //大小
        this.setSize(500,300);
        //位置
        this.setLocation(500,200);
        //关闭窗口程序结束
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗体可见
        this.setVisible(true);

        //客户端通信
        Socket socket=null;
        out=null;
        //BufferedReader sin=null;
        BufferedReader in=null;

        //监听按钮
        jButtonText.addActionListener(this);
        jButtonFile.addActionListener(this);
        //监听文本框
        jTextField.addKeyListener(this);
        try {
            //绑定服务器地址 端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 8888;
            //创建链接
            socket = new Socket(serverIP, port);
            //标准输入设备构造BufferedReader 对象
            //sin=new BufferedReader(new
             //       InputStreamReader(System.in));
            //由socket获得io对象
            out=new PrintWriter(socket.getOutputStream());
            in=new BufferedReader(new
                    InputStreamReader(socket.getInputStream()));
            while (true){
                jta.append(in.readLine()+System.lineSeparator());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(in!=null)
            {
                try{
                    in.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }if(out!=null)
            {
                try{
                    out.close();
                }catch (UnknownError e) {
                    e.printStackTrace();
                }
            }if(socket!=null){
                try{
                    socket.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //行为

    private void SendTextToSocket(){
        String text= jTextField.getText();
        jta.append("我说:"+text+System.lineSeparator());
        try {
            out.println(text);
            out.flush();
            //清空文本框
            jTextField.setText("");
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("发送")){
            SendTextToSocket();
        }
        else {
            new filePanel();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {


    }

    @Override
    public void keyPressed(KeyEvent e) {
        //按下回车
        if(e.getKeyCode()==KeyEvent.VK_ENTER){
            SendTextToSocket();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

}

发送文件界面

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

class filePanel extends JFrame implements ActionListener {
    //属性
    //文本域
    private final JTextArea jta;
    //滚动条
    private final JScrollPane jsp;
    //面板
    private final JPanel jp;
    //文本框
    private final JTextField jtf;
    //按钮
    private final JButton jb;

    //构造方法
    public filePanel(){
        //初始化
        jta = new JTextArea();
        //文本域默认不可编辑
        jta.setEditable(false);
        jsp = new JScrollPane(jta);//将文本域添加到滚动条中
        jp = new JPanel();
        jtf = new JTextField(25);
        jb = new JButton("发送");
        //将文本框与按钮添加到面板中
        jp.add(jtf);
        jp.add(jb);
        //将滚动条与面板添加到窗体中
        this.add(jsp, BorderLayout.CENTER);
        this.add(jp, BorderLayout.SOUTH);

        //标题
        this.setTitle("发送文件");
        //文本域
        jta.setText("请输入要发送的文件地址");
        //大小
        this.setSize(400, 150);
        //位置
        this.setLocation(600, 300);
        //关闭时隐藏并释放窗口
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        //设置窗体可见
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        DatagramSocket socket= null;
        try {
            socket = new DatagramSocket();
            byte[] buf=new byte[256];
            InetAddress address=InetAddress.getByName("127.0.0.1");

            DatagramPacket packet=new DatagramPacket(buf, buf.length, address, 9999);
            socket.send(packet);

            packet=new DatagramPacket(buf,buf.length);
            socket.receive(packet);
            String received=new String(packet.getData());

            System.out.println("Quote of the Moment:"+received );
            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值