socket实现简单的多人聊天室

时间:2022-04-22 10:18:05

服务端Server.java

package chatDemo;

import java.awt.BorderLayout;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map.Entry;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


public class Server extends JFrame {
private JTextArea txt = new JTextArea("服务器已经启动");
private ServerSocket serverSocket = null;
private static Map<Socket, Integer> list = new LinkedHashMap<Socket,Integer>();
private ExecutorService exec= null;

public Server() throws IOException{
setLayout(new BorderLayout());
this.add(new JScrollPane(txt),BorderLayout.CENTER);
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

//启动服务器
serverSocket = new ServerSocket(54321);
//创建线程池
exec = Executors.newCachedThreadPool();
//服务器通过accept()方法产生阻塞,接受客户端连接
while(true){
//构造器也是一个进程?不然这里while会把主线程卡死?
Socket socket = null;
//接收到客户端连接
socket = serverSocket.accept();
System.out.println(1);
//将每次连接的client加入到list中。
list.put(socket,socket.getPort());
//启动线程,用于不停地从服务器端读取数据
exec.execute(new Communication(socket));
}
}

public class Communication implements Runnable {
private Socket socket;
//用于接收从客户端发送过来的信息
private DataInputStream fromClient =null;
//用于向客户端发送信息
private DataOutputStream toClient = null;
private String msg;

public Communication(Socket socket) throws IOException{
this.socket = socket;
fromClient = new DataInputStream(socket.getInputStream());
msg ="["+socket.getPort()+ "]已连接到服务器";
txt.append(msg+"\n");
sendMessage();
msg="";
}

@Override
public void run() {
try {
while((msg= fromClient.readUTF())!=null){
msg = "[" + socket.getPort() + "]:"+ msg;
txt.append(msg+"\n");
sendMessage();
}
} catch (Exception e) {
}

}

//将从客服端接收到的信息,循环发送到所有客户端
public void sendMessage() {
Iterator it = list.entrySet().iterator();
while (it.hasNext()) {
Entry entry = (Entry) it.next();
Socket client =(Socket) entry.getKey();
int port = (Integer) entry.getValue();
//如果部分客户端关闭了,此处如果用throws exception数据将无法发送打客户端,用try catch可以继续通信
try{
toClient = new DataOutputStream(client.getOutputStream());
toClient.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) throws IOException {
Server server = new Server();
}
}



客户端Client.java

package chatDemo;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;

public class Client extends JFrame{
private JButton conn = new JButton("connect");
private JTextArea txt = new JTextArea("");
private JTextField edt = new JTextField("");
private JButton send = new JButton("发送");
private JPanel p1 = new JPanel();
private JPanel p2 = new JPanel();
private ExecutorService exec= null;
private Socket clientSocket = null;
private DataInputStream fromServer;
private DataOutputStream toServer;

public Client(){
setLayout(new BorderLayout());
p1.setLayout(new BorderLayout());
p2.setLayout(new BorderLayout());
p1.add(edt,BorderLayout.CENTER);
p1.add(send,BorderLayout.EAST);

p2.add(new JScrollPane(txt),BorderLayout.CENTER);
p2.add(p1,BorderLayout.SOUTH);
p2.add(conn,BorderLayout.NORTH);

this.add(p2,BorderLayout.CENTER);
setSize(500,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//启动客户端,连接到服务器
conn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//创建线程池,并执行线程
exec = Executors.newCachedThreadPool();
exec.execute(new ClientSocket());
}
});

//往服务器发送数据
send.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
toServer.writeUTF(edt.getText());
toServer.flush();
edt.setText("");
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});

}

//创建客户端socket线程,用于不停地读取服务器发送过来 的数据
class ClientSocket implements Runnable{
@Override
public void run() {
try {
clientSocket = new Socket("localhost", 54321);
fromServer = new DataInputStream(clientSocket.getInputStream());
toServer = new DataOutputStream(clientSocket.getOutputStream());

while (true) {
String msg = fromServer.readUTF();
if (msg != null)
txt.append(msg + "\n");
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
Client client = new Client();
}
}