作者:0o墨滴成殇 | 来源:互联网 | 2023-12-11 15:55
本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。
一、 Socket简介
点击超链接查看: socket与HTTP的区别
二、两个或多个客户端之间进行聊天
1、 服务器端
(1) 实体类:
原理:每个用户都有自己的socket套接字,也就是每个用户都有自己的输出流和输入流,只要用某个用户的输出流 进行输出,某个用户就可以接收到消息。
public class SocketUser {
private String name;
private String account;
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public BufferedReader getBr() {
return br;
}
public void setBr(BufferedReader br) {
this.br = br;
}
public PrintWriter getPw() {
return pw;
}
public void setPw(PrintWriter pw) {
this.pw = pw;
}
public SocketUser(String name, final Socket socket) throws IOException{
this.name = name;
this.socket = socket;
//读取客户端传输的 输入流
this.br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
//转发给客户端的 输出流
this.pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"),true);
}
@Override
public String toString() {
return "SocketUser{" +
"name='" + name + '\'' +
", account='" + account + '\'' +
", socket=" + socket +
'}';
}
}
(2) 服务器的监听代码
@Service
public class ServerSocket1 {
private ServerSocket serverSocket;
public void ServerSocketDemo(){
int count=0;
try{
//存放 连接上服务器的用户 列表
List list = new ArrayList();
serverSocket=new ServerSocket(5555);//开启服务的端口,需和客户端一致
System.out.println("服务端已经启动,等待客户端连接");
while (true){
Socket socket=serverSocket.accept();
count++;
SocketUser user = new SocketUser("user" + count,socket);
System.out.println(user.getName() + "正在登录。。。");
list.add(user);//把新增的用户添加到list里面
System.out.println(list);
System.out.println("客户端的IP:"+socket.getInetAddress().getHostAddress());
new ServerThread2(user,list).start();//开启输入和输出的多线程
}
}catch (IOException exception){
exception.printStackTrace();
}
}
}
(3) 读取消息,转发消息
public class ServerThread2 extends Thread {
private SocketUser user;
private List list;
public ServerThread2(SocketUser user, List list) {
this.user = user;
this.list = list;
}
public void run() {
try {
while (true) {
// 信息的格式:(add||remove||chat),收件人,...,收件人,发件人,信息体
//不断地读取客户端发过来的信息
String msg = user.getBr().readLine();
System.out.println(msg);
String[] str = msg.split(",");
int i=str.length;
System.out.println(i);
//转发消息
switch (str[0]) {
case "remove":
remove(user);// 移除用户,此处仅仅只是从list中移除用户
break;
case "chat":
// 转发信息给特定的用户,单发或群发
for (int a=1;a<=i-3;a++) {
sendToClient(str[a], msg);
}
break;
case "add":
addUser(user);//添加用户,此处仅仅是list中添加用户
default:
break;
}
}
} catch (Exception e) {
System.out.println("消息回复异常");
} finally {
try {
user.getBr().close();
user.getSocket().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//在用户列表中添加用户信息
private void addUser(SocketUser user) {
list.add(user);
System.out.println(list);
}
//转发消息
private void sendToClient(String username, String msg) {
for (SocketUser user : list) {
if (user.getName().equals(username)) {
try {
PrintWriter pw =user.getPw();
pw.println(msg);
pw.flush();
System.out.println("消息转发成功!");
break;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//从用户列表中删除用户
private void remove(SocketUser user2) {
list.remove(user2);
System.out.println(list);
}
}
2、 客户端实现
public class newThread {
public static final String IP = "192.168.1.105";//服务器地址
public static void main(String[] args) {
try {
Socket socket = new Socket(IP, 5555); //ip,port
//开启多线程接收信息,并解析
ClientThread thread=new ClientThread(socket);
thread.start();
//主线程用来发送信息
BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); //从控制台输入
PrintWriter out=new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"),true);
while(true)
{
String s=br.readLine();
out.println(s);
out.flush();
}
}catch(Exception e){
System.out.println("服务器异常");
}
}
}
public class ClientThread extends Thread{
private Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
try {
// 信息的格式:(add||remove||chat),发送人,收发人,信息体
while (true) {
String msg=br.readLine();
System.out.println(msg);
String[] str = msg.split(",");
int i=str.length;
switch (str[0]) {
case "chat":
System.out.println(str[i-2] + " 说: "
+ str[i-1]);
break;
default:
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
以上就是实现的所有代码,运行效果如下:
再次之前需要mapping一下,以便开始服务
@GetMapping("/test1")
public void test1(){
serverSocket1.ServerSocketDemo();
}
开启之后:
运行客户端代码:运行三个客户端
演示聊天功能:
在控制台输入: chat,user2,user3,user1,this is a test!