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;
}