简述
实现过程 如果要让 客户端和客户端进行交流 必须要通过服务端 进行转发数据.
这样 客户端 --数据-- 服务端 --数据-- 客户端 . 每一个 客户端 就有一个socket对象 被服务端保存.
socket TCP的通信原理和基本概念建议参考
https://www.cnblogs.com/linkenpark/p/11289018.html
服务器 主要功能 保存 接收到的用户 和转发用户发过来的消息.
服务器端代码
public class ServerSoc {
private final static int PORT = 9999;
public static HashMap socketList = new HashMap<>(); // 在线列表
public static String channelToken; //socket 令牌
private static BufferedReader bufferedReader;
private Common common = new Common();
// 客户端之间发送消息
public void clientToclient(String C1, String C2,HashMap<String, Socket> map){
new Thread(new Runnable() {
@Override
public void run() {
while (true){
common.toMessage(C1, C2, map);
}
}
}).start();
public static void main(String[] args) {
try{
Common common = new Common();
ServerSoc serverSoc = new ServerSoc();
ServerSocket server= new ServerSocket(PORT);
System.out.println("server is listenning...");
while(true){
//不断循环随时等待新的客户端接入服务器
Socket clientSocket =server.accept();
//接收客户端的消息 clientSocket.getInputStream()
bufferedReader= new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 读取发送过来的信息
channelToken=bufferedReader.readLine();
System.out.println("用户输入的channelToken: "+channelToken);
String name = null;
if(channelToken.contains("name: ")){
name = channelToken.substring(channelToken.indexOf(": ")+1).trim();
socketList.put(name,clientSocket);//保存会话ID和socket
common.writerMessage(clientSocket, "欢迎"+name+"来到这里聊天");
}
if(socketList.size() > 1){
System.out.println(socketList); // 输出列表中的socket对象
// 暂时只接受 名字为 Jack和Tom 的用户
serverSoc.clientToclient("Jack","Tom",socketList);
serverSoc.clientToclient("Tom","Jack",socketList);
}
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
客户端功能 将服务器发送的数据接收 输出 写数据发给服务器
客户端代码
public class SocketClient {
public static void main(String[] args) throws IOException {
Common common = new Common();
//初始化socket并且绑定9999端口
Socket socket = new Socket("localhost", 9999);
// 线程 一直读取服务端的消息
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(common.readerMessage(socket));
}
}
}).start();
try {
// 将数据写到输出流 完发送到服务端 socket.getOutputStream()
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//获取输入流 指定编码
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
String str;
//输入名字
System.out.println("请输入姓名, 格式name: Tom");
// 获取数据
while (true){
// 写数据给 服务端
str = bufferedReader.readLine();
if (str != null){
bufferedWriter.write(str);
bufferedWriter.write("\n");
bufferedWriter.flush();
}
}
}catch (IOException e){
e.printStackTrace();
}
}
}
公共类 提供一些公共的方法
public class Common {
private BufferedWriter out;
// 向其他用户 发送信息
public void toMessage(String name, String name2, HashMap<String, Socket> map){
Socket socket = map.get(name);
Socket socket2 = map.get(name2);
String str1 = null;
// 读取客户端一发送给服务器的数据
str1 = readerMessage(socket);
// 向其他客户端发送消息
if(str1 != null){
writerMessage(socket2, name+"说: "+str1);
System.out.println(name+"对"+name2+"说>>>> "+str1);
}
}
// 读取其他用户发送给服务器的信息
public String readerMessage(Socket socket){
try {
//获取输入流 指定编码
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
// 获取数据
String str;
if ((str = bufferedReader.readLine()) != null){
return str;
}
}catch (IOException e){
e.printStackTrace();
}
return null;
}
// 服务端向指定客户端发送消息
public void writerMessage(Socket socket, String message){
try{
// 发送到对应的客户端数据
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//回复client的ID
out.write(message);
out.write("\n");
out.flush();
}catch(IOException e) {
e.printStackTrace();
}
}
运行过程:
首先启动 服务端
客户端
注意:
BufferedReader/BufferedWriter 在读取 消息的时候会 进行阻塞 等待接收到消息后才能进行后续程序
异常相关: https://blog.csdn.net/weixin_43272781/article/details/103231958
idea 开启二个相同的Java程序: https://blog.csdn.net/Gu_fCSDN/article/details/106208275