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

该博客主要讨论了一个Java Socket编程的问题,即客户端断开连接后重新连接,能发送消息给服务器但无法接收到服务器的响应。问题出现在服务器端的广播消息环节,可能由于未正确处理已断开的连接导致。代码示例展示了服务器和客户端的实现,包括线程池的使用,以及键盘和按钮事件监听。
摘要由CSDN通过智能技术生成

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

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

服务器端代码:

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值