需求
1.客户端登陆功能
可以启动客户端进行登录,客户端登陆只需要输入用户名和服务端ip地址即可。
⒉在线人数实时更新。
客户端用户户登陆以后,需要同步更新所有客户端的联系人信息栏。
3.离线人数更新
检测到有客户端下线后,需要同步更新所有客户端的联系人信息栏。
4.群聊
任意一个客户端的消息,可以推送给当前所有客户端接收。
5.私聊
可以选择某个员工,点击私聊按钮,然后发出的消息可以被该客户端单独接收。
黑马的IO视频采用GUI设计,我这里直接在控制台打印实现,简单实现了群聊与私聊功能。
演示图:
实现代码:
Server:
public class Server {
//public static List<Socket> allOnlineSocket = new ArrayList<>();
public static Map<Socket,String> allOnlineSocket = new HashMap<>();
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(9999);
while (true) {
Socket socket = ss.accept();
// 用户登录
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String username = br.readLine();
allOnlineSocket.put(socket,username);
System.out.println(username+" 上线");
new Thread(new ServerSocketRunnable(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ServerSocketRunnable
public class ServerSocketRunnable implements Runnable{
private Socket socket;
public ServerSocketRunnable(Socket socket) {
this.socket = socket;
}
/*
定义:
1:全体消息 格式: 1,信息
2:私聊消息 格式: 2,用户名,信息
*/
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg = br.readLine()) != null) {
System.out.println("收到消息:"+msg);
String flag = msg.substring(0, 1);
if ("1".equals(flag)) {
// 群聊
String data = msg.substring(2);
sendMstToAllUser(data);
}else if("2".equals(flag)){
// 私聊
int index = msg.indexOf(",",2);
String username = msg.substring(2,index);
String data = msg.substring(index+1);
System.out.println("username = " + username + ",data = " + data);
sendToOneUser(username,data);
}
}
}catch (Exception e) {
// e.printStackTrace();
// 有用户下线
System.out.println(Server.allOnlineSocket.get(socket) + "用户下线!");
Server.allOnlineSocket.remove(socket);
}
}
// 私聊
private void sendToOneUser(String username, String data) {
// 推送信息
Server.allOnlineSocket.forEach((socket, name) -> {
if (name.equals(username)) {
try {
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println(data);
ps.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
// 群聊
private void sendMstToAllUser(String msg) {
System.out.println("当前在线socket有:");
Server.allOnlineSocket.forEach((sk, username) -> {
System.out.print(username+",");
});
System.out.println();
// 推送信息
Set<Socket> set = Server.allOnlineSocket.keySet();
set.forEach(skk -> {
try {
OutputStream os = skk.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println(msg);
ps.flush();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
Client:
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 9999);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
new Thread(new ClientSocketRunnable(socket)).start();
Scanner sc = new Scanner(System.in);
while (true) {
String msg = sc.nextLine();
ps.println(msg);
ps.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientSocketRunnable:
public class ClientSocketRunnable implements Runnable{
private Socket socket;
public ClientSocketRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg = br.readLine()) != null) {
System.out.println("客户端收到:"+msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}