即时通信-群聊
即时通信-群聊
群聊是要把客户端的消息发给多个客户端。
TCP通信-端口转发
服务端代码:
- 在此基础上修改:TCP支持多个客户端通信#^e44c74
public class ServerDemo {
public static List<Socket> onLineSockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
// 创建ServerSocket对象
ServerSocket ss = new ServerSocket(10000);
while(true) {
// 调用accept等待客户端连接
Socket accept = ss.accept();
onLineSockets.add(socket);
System.out.println("有人上线了:" + socket.getRemoteSocketAddress());
// 把这个客户端对应的socket通信管道,交给一个独立的线程负责
new ServerReaderThread(accept).start();
}
}
}
服务端读数据的多线程代码修改
public class ServerReaderThread extends Thread {
private Socket socket;
public ServerReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 获取输入流对象
InputStream is = accept.getInputStream();
// 把原始的字节输入流包装称数据输入流
DataInputStream dis = new DataInputStream(is);
while(true) {
try {
// 使用数据输入流读取客户端发送过来的消息
String rs = dis.readUTF();
System.out.println(rs);
// 把这个消息分发给全部客户端进行接收
sendMsgToAll(rs);
// 获取客户端的IP地址
System.out.println(accept.getRemoteSocketAddress());
} catch(Exception e) {
System.out.println(socket.getRemoteSocketAddress() + "离线了");
Server.onLineSockets.remove(socket);
dis.close();
socket.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendMsgToAll(String msg) throw IOException{
// 发送给全部在线的socket管道接收
for (Socket onLineSocket : Server.onLineSockets) {
OutputStream os = onLineSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(msg);
dos.flush();
}
}
}
客户端代码:基于TCP多收多发#^889e2d修改
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建一个Socket对象
Socket socket = new Socket("127.0.0.1", 10000);
// 创建一个独立线程,负责随机从socket中接收服务端发送过来的消息
new ClientReaderThread(socket).start();
// 获取一个IO流开始写数据
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;
}
// 开始写数据
dos.writeUTF("Hello, server");
dos.flush();
}
// 释放资源
dos.close();
socket.close();
}
}
客户端读取数据的线程
public class ClientReaderThread extends Thread{
private Socket socket;
public ClientReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 获取输入流对象
InputStream is = accept.getInputStream();
// 把原始的字节输入流包装称数据输入流
DataInputStream dis = new DataInputStream(is);
while(true) {
try {
// 使用数据输入流读取客户端发送过来的消息
String rs = dis.readUTF();
System.out.println(rs);
// 获取客户端的IP地址
System.out.println(accept.getRemoteSocketAddress());
} catch(Exception e) {
System.out.println("自己下线了:" + socket.getRemoteSocketAddress());
dis.close();
socket.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}