实现多人群聊
Client(客户端)建立通信
package com.zz.tcp.case1;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String args[]) throws Exception {
//1.创建Socket对象,并同时请求与服务端程序连接
Socket socket = new Socket("127.0.0.1", 8888);
//创建一个独立的线程,负责随机从socket中接收服务端的发送过来的消息
new ClientReaderThread(socket).start();
//2.从socket通信管道中的到一个字节输出流,用来发送数据
OutputStream os = socket.getOutputStream();
//将低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
Scanner sc = new Scanner(System.in);
while(true){
System.out.println("请说:");
String msg = sc.nextLine();
//一旦用户输入了exit就退出客户端程序
if("exit".equals(msg)){
System.out.println("欢迎您下次光临!");
dos.close();
socket.close();
break;
}
//4.开始写数据出去
dos.writeUTF(msg);
//5.刷新数据,防止数据留在管道
dos.flush();
}
}
}
ClientReaderThread(服务端线程类)——实现接收服务端转发的消息
package com.zz.tcp.case1;
import java.io.*;
import java.net.Socket;
public class ClientReaderThread extends Thread{
private Socket socket;
public ClientReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
String msg = dis.readUTF();
System.out.println(msg);
//把这个消息发送给全部客户端进行接收
sendMsgToAll(msg);
} catch (Exception e) {
System.out.println("自己下线了" + socket.getRemoteSocketAddress());
dis.close();
socket.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendMsgToAll(String msg) throws IOException {
//发送给全部在线的socket的管道接收
for (Socket onLineSocket: Server.onLineSockets) {
OutputStream os = onLineSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(msg);
dos.flush();
}
}
}
Server(服务端)负责接收客户端的消息,通过8888端口建立连接
package com.zz.tcp.case1;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static List<Socket> onLineSockets = new ArrayList <>();
public static void main(String args[]) throws Exception{
System.out.println("========服务端启动========");
//1.创建ServerSocket的对象,调用一个accept方法,等待客户端的连接请求
ServerSocket serverSocket = new ServerSocket(8888);
while (true){
//2.使用ServerSocket对象,调用一个accept方法,等待客户端的连接请求
Socket socket = serverSocket.accept();
onLineSockets.add(socket);
System.out.println("有人上线了" + socket.getRemoteSocketAddress());
//3.把这个客户端对应的socket通信管道,交给一个独立的线程复制处理
new ServerReaderThread(socket).start();
}
}
}
ServerReaderThread(客户端线程类)——负责接受客户端发的消息,然后转发给其他客户端
package com.zz.tcp.case1;
import java.io.*;
import java.net.Socket;
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
while (true) {
try {
String msg = dis.readUTF();
System.out.println(msg);
//把这个消息发送给全部客户端进行接收
sendMsgToAll(msg);
} catch (Exception e) {
System.out.println("有人下线了" + socket.getRemoteSocketAddress());
Server.onLineSockets.remove(socket);
dis.close();
socket.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendMsgToAll(String msg) throws IOException {
//发送给全部在线的socket的管道接收
for (Socket onLineSocket: Server.onLineSockets) {
OutputStream os = onLineSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(msg);
dos.flush();
}
}
}