欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java socket 多客户端连一个服务器端问题

程序员文章站 2024-03-23 09:48:40
...

某一个客户端断开连接后再连接,可以发消息给服务器端,但是接收不到服务器端的消息,或者就是服务器端不会发消息给它。

以下是代码,希望大佬指点一二

服务器端代码:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

public class ChatRoomServer {
    public static void main(String[] args) {
        JFrame f=new JFrame("Server");
        f.setBounds(200,200,600,600);
        f.setLayout(null);
        JPanel p1=new JPanel();
        p1.setBounds(1,1,400,400);
        p1.setLayout(null);
        JPanel p2=new JPanel();
        p2.setBounds(1,401,400,190);
        p2.setLayout(null);
        JTextArea jta=new JTextArea();
        jta.setBounds(2,2,300,390);
        JTextField jtf=new JTextField();
        jtf.setBounds(50,50,200,80);
        JButton b=new JButton("发送");
        b.setBounds(280,80,80,30);

        p1.add(jta);
        p2.add(jtf);
        p2.add(b);
        f.add(p1);
        f.add(p2);
        //焦点给键盘,因为键盘监听和按钮监听会有冲突
        b.setFocusable(false);
        //存储建立的连接
        List<Socket> sockets=new ArrayList<>();
        try {

            b.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    try {
                        String send=jtf.getText();
                        if(send!="")
                        {
                            jta.append("server: "+send+"\r\n");
                            jtf.setText("");
                            for(Socket s:sockets)
                            {
                                //不进行判断的话,一个客户端断开连接其它客户端也收不到消息
                                if(s!=null)
                                {
                                    OutputStream os = s.getOutputStream();
                                    DataOutputStream dos = new DataOutputStream(os);
                                    dos.writeUTF("server: "+send);
                                }

                            }
                        }
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            });
            jtf.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    super.keyTyped(e);
                    if(e.getKeyChar() == KeyEvent.VK_ENTER)
                    {
                        try {
                            String send=jtf.getText();
                            if(send!="")
                            {
                                jta.append("server: "+send+"\r\n");
                                jtf.setText("");
                                for(Socket s:sockets)
                                {
                                    if(s!=null)
                                    {
                                        OutputStream os = s.getOutputStream();
                                        DataOutputStream dos = new DataOutputStream(os);
                                        dos.writeUTF("server: "+send);
                                    }
                                }
                            }
                        }
                        catch (Exception e1)
                        {
                            e1.printStackTrace();
                        }
                    }

                }
            });
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        try {
            ServerSocket ss = new ServerSocket(8888);
            System.out.println("监听端口号:8888");
            ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10,
                    15, 60, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>());
            /*
            第一个参数10 表示这个线程池初始化了10个线程在里面工作
            第二个参数15 表示如果10个线程不够用了,就会自动增加到最多15个线程
            第三个参数60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,
            多出来的线程还没有接到活儿,就会回收,最后保持池子里就10个
            第四个参数TimeUnit.SECONDS 如上
            第五个参数 new LinkedBlockingQueue() 用来放任务的集合
             */


            while(true)
            {
                Socket s=ss.accept();
                sockets.add(s);
                threadPool.execute(new ServerThread(s,sockets,jta));

            }


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



    }
}
class ServerThread implements Runnable
{
    Socket s;
    List<Socket> sockets;
    JTextArea jta;
    public ServerThread(Socket s,List<Socket> sockets,JTextArea jta)
    {
        this.s=s;
        this.sockets=sockets;
        this.jta=jta;
    }
    @Override
    public void run() {
        while(true)
        {
            if(!s.isClosed())
            {
                try {
                    InputStream is = s.getInputStream();
                    DataInputStream dis = new DataInputStream(is);
                    if(is.available()>0)
                    {
                        String receive =dis.readUTF();
                        if(receive=="client disconnection")
                        {
                            jta.append(s.getRemoteSocketAddress()+": " + receive + "\r\n");
                            for(Socket s1:sockets)
                            {
                                if(s1.getRemoteSocketAddress()==s.getRemoteSocketAddress())
                                {
                                    sockets.remove(s1);
                                }
                            }//System.out.println("gg");
                            s.shutdownInput();
                            s.shutdownOutput();
                            s.close();
                            break;
                        }
                        else if(receive!="")
                        {
                            String sip=String.valueOf(s.getRemoteSocketAddress());
                            {
                                jta.append(s.getRemoteSocketAddress()+": " + receive + "\r\n");
                                for(Socket s:sockets)
                                {
                                    if(s!=null)
                                    {
                                        OutputStream os = s.getOutputStream();
                                        DataOutputStream dos = new DataOutputStream(os);
                                        dos.writeUTF(sip+": "+receive);
                                    }


                                }
                            }

                        }
                    }


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

        }

    }
}

客户端代码:



import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class ChatRoomClient {
    public static int flag=1;
    public static void main(String[] args) {
        JFrame f=new JFrame("Client");
        f.setBounds(200,200,600,600);
        f.setLayout(null);
        JPanel p1=new JPanel();
        p1.setBounds(1,1,400,400);
        p1.setLayout(null);
        JPanel p2=new JPanel();
        p2.setBounds(1,401,400,190);
        p2.setLayout(null);
        JTextArea jta=new JTextArea();
        jta.setBounds(2,2,300,390);
        JTextField jtf=new JTextField();
        jtf.setBounds(50,50,200,80);
        JButton b=new JButton("发送");
        b.setBounds(280,80,80,30);

        p1.add(jta);
        p2.add(jtf);
        p2.add(b);
        f.add(p1);
        f.add(p2);
        //焦点给键盘,因为键盘监听和按钮监听会有冲突
        b.setFocusable(false);
        //窗口关闭就关闭socket
        //要用windowClosing不能用windowClosed。而且要调用dispose();方法


        try {
            String ip ="127.0.0.1";
            Socket s = new Socket(ip,8888);
            System.out.println("监听端口号:8888");
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            f.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    super.windowClosing(e);
                    try {
                        dos.writeUTF("client disconnection");
                        flag=0;
                        s.shutdownOutput();
                        s.close();
                        //System.out.println("gg");
                    }
                    catch (Exception e1)
                    {
                        e1.printStackTrace();
                    }
                    f.dispose();
                }
            });
            //接收
            Thread t1 = new Thread() {
                public void run() {
                    //线程的While(true)里面放要循环的内容需要不停执行的内容
                    while (true) {

                            if(flag==1&&!s.isClosed())
                            {
                                try {
                                    String s = dis.readUTF();
                                    if (s != "") {
                                        jta.append(s + "\r\n");
                                        p1.updateUI();
                                    }
                                } catch (IOException e) {
                                    // TODO 自动生成的 catch 块
                                    e.printStackTrace();
                                }
                            }
                            else
                            {
                                break;
                            }
                        }

                        }



            };
            t1.start();
            b.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {


                    String s1=jtf.getText();
                        if(s1!="")
                        {
                            try {
                                dos.writeUTF(s1);
                                jtf.setText("");

                            }
                            catch (Exception e1)
                            {
                                e1.printStackTrace();
                            }
                        }
                    }


            });
            jtf.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    super.keyTyped(e);
                    if(e.getKeyChar() == KeyEvent.VK_ENTER)
                    {
                        String s1=jtf.getText();
                            if(s1!="")
                            {
                                try {
                                    dos.writeUTF(s1);
                                    jtf.setText("");

                                }
                                catch (Exception e1)
                                {
                                    e1.printStackTrace();
                                }
                            }


                    }
                }
            });

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



        //f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}

module-info

module study {
	requires java.sql;
	requires java.desktop;

}