在之前的功能基础上,可以区分开群聊和私聊
引入哈希表来实现,具体代码如下:
客户端类:
public class MClient {
//创建客户端 Socket 再获取输入输出流 启动线程不实时读取服务器发来的消息 String msg 再写一个发送消息 Scanner scan
//写发送消息的方法 sendMsg (os) 写读取指定长度数据 readMsg()用到保存消息的缓冲区 byte[]
public static void main(String[] args) throws IOException {
new MClient().StartMClient();
}
public OutputStream os;
public InputStream is;
public void StartMClient() throws IOException {
//创建客户端
Socket socket = new Socket("127.0.0.1",9999);
//获取输入输出流
is = socket.getInputStream();
os = socket.getOutputStream();
//启动线程时不实时读取消息
new Thread(new Runnable() {
@Override
public void run() {
while(true){
String msg = null;
try {
msg = readMsg();
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println(msg);
}
}
}).start();
//发送消息
while(true){
Scanner scan = new Scanner(System.in);//从键盘获得输入
String line = scan.nextLine();
sendMsg(line);
}
}
//读取消息
public String readMsg() throws IOException {
byte[] b = new byte[1024];
is.read(b);
String msg = new String(b);
return msg.trim();
}
//发送消息
public void sendMsg(String msg) throws IOException {
String str = msg + "\r\n";
os.write(str.getBytes());
os.flush();
}
}
服务器端:
public class MServer {
public static void main(String[] args) throws IOException {
new MServer().StartMServer();
}
public void StartMServer() throws IOException {
//创建一个服务器 用哈希表Map<Integer,Socket> map存用户客户端 给用户端设一个ID用来
//连接客户端server.accept 并放到哈希表 启动线程 保持通信状态
ServerSocket server = new ServerSocket(9999);
Map<Integer, Socket> map = new HashMap<>();
int UserID = 1;
while(true){
//连接客户端 把客户端添加到map中
Socket socket = server.accept();
map.put(UserID,socket);
//启动线程 保持通信
ServerThread serverThread = new ServerThread(socket,map,UserID++);
new Thread(serverThread).start();
}
}
}
线程通信类:
public class ServerThread implements Runnable {
public Socket socket;
public OutputStream os;
public InputStream is;
public Map<Integer,Socket> map;
public int UserID;
public ServerThread(Socket socket,Map<Integer,Socket> map,int UserID){
this.socket = socket;
this.map = map;
this.UserID = UserID;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
sendMsg(UserID,os,"客户端连接成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void run() {
//读取msg 再去分析msg是广播还是私聊对msg进行分割
while(true){
try {
String msg = readMsg();
String[] msgArr = msg.split(":");
if(msgArr[0].equals("g")){
//群发
for(Map.Entry<Integer,Socket> entry : map.entrySet()){
Socket s = entry.getValue();
if(s != socket){
OutputStream output = s.getOutputStream();
sendMsg(UserID,output,msg);
}
}
}else{
//私聊
Integer id = Integer.parseInt(msgArr[0]);
//根据id找到对象
Socket s = map.get(id);
OutputStream output = s.getOutputStream();
sendMsg(UserID,output,msgArr[1]);
}
System.out.println("client : " + msg);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//读取消息
public String readMsg() throws IOException {
byte[] b = new byte[1024];
is.read(b);
String msg = new String(b);
return msg.trim();
}
//发送消息
public void sendMsg(int UserId,OutputStream os,String msg) throws IOException {
String str =UserId + ":" + " " + msg + "\r\n";
os.write(str.getBytes());
os.flush();
}
}