java例题:实现多客户聊天
程序员文章站
2022-03-15 20:35:11
...
java 实现多客户端聊天(TCP)
1. 编程思想:
- 要想实现多客户端聊天,首先需要有多个客户端,而这些客户端需要随时发送消息和接受消息,所以收发消息需要放入不同的线程中。
- 多客户聊天并不是多个客户之间进行两两通信,而是需要所有客户端与服务端进行交互,再由服务端统一下发信息到其他参与聊天的客户端。
2. 代码实现:
2.1 实现专用于接收消息的子线程ReceiveThread
将接收消息和发送消息分为两个线程,其中将发送消息写入主线程中,开启新的线程用于接收消息。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ReceiveThread extends Thread{
private Socket socket; //私有的成员变量,套接字
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;//使用带缓冲区的字符输入流接收信息
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
while(true){
try {
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.2 客户端代码
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
@SuppressWarnings("all")
public static void main(String[] args) throws UnknownHostException, IOException {
//ip:需要连接的服务端所在的ip
//端口:客户端连接的端口必须和服务端端口一致
Socket socket = new Socket("192.168.*.*",8080);
Scanner scan = new Scanner(System.in);
new ReceiveThread(socket).start();
//发送给服务端信息
while(true ){
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("一号:"+scan.next());
}
}
}
注:
-
客户端代码可以在局域网下的多台电脑上运行,只需要将ip地址改为服务端的ip,就能够连接。
-
如果想要使用同台电脑完成一个服务端和两个客户端运行,进行测试多人聊天,可创建客户端2,使用本机ip
Socket socket = new Socket("127.0.0.1",8080); Scanner scan = new Scanner(System.in); new ReceiveThread(socket).start(); //发送给服务端信息 while(true ){ PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("二号:"+scan.next()); }
2.3 服务端接收和转发信息的线程ServerThread
服务端在每一个客户端进行连接时,都会产生一个线程,用于服务这个客户,负责接收该客户发送的信息,并转发到参与多人聊天的其他客户。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Map.Entry;
import java.util.Set;
public class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
String str=null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
while(true){
try {
str=br.readLine();
//在服务端输出,可以监测到所有人的聊天信息。
System.out.println(str);
//发送到其他客户端
Set<Entry<InetAddress, Socket>> entrySet = Server.map.entrySet();
for (Entry<InetAddress, Socket> entry : entrySet) {
InetAddress key = entry.getKey();
Socket value = entry.getValue();
if(socket.getInetAddress()!=key){
PrintStream printStream = new PrintStream(value.getOutputStream());
printStream.println(str);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.4 服务端代码
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
public class Server {
@SuppressWarnings("all")
public static ConcurrentHashMap<InetAddress, Socket> map =new ConcurrentHashMap<>();
public static void main(String[] args) throws IOException, InterruptedException {
//创建服务端的ServerSocket
ServerSocket server = new ServerSocket(8080);
while(true){
//接收到客户连接就创建一个对应的套接字
Socket socket = server.accept();
//获取该客户的ip
InetAddress inetAddress = socket.getInetAddress();
//将该客户的ip和套接字装入map集合
map.put(inetAddress, socket);
//创建新的线程服务该客户
new ServerThread(socket).start();
}
}
}