(一)登录
- 1.定义一个接口来对整个代码进行规范
public interface Chat {
//登录
String LOGIN_FLAG = "u+";
//私聊
String PRIVATE_FLAG = "p+";
//群聊
String PUBLIC_FLAG = "a+";
//分隔符
String SPLIT_FLAG = "♥";
//成功的状态
String SUCCESS = "1";
//失败状态
String FAILURE = "-1";
}
- 2.定义UserManager类 管理所有登录⽤的信息
public class UserMannager {//保存所有用户信息
private Map users= new HashMap<>();
/**
* 判断用户是否登陆
*/
public boolean isLogined(String name){
//遍历数组
for (String key:users.keySet()) {
if(key.equals(name)){
return true;
}
}
return false;
}
/**
* 保存当前登录的用户信息
*/
public void save(String name,Socket socket){
users.put(name,socket);
}
/**
* 通过用户名找到对应的socket
*/
public Socket socketByname(String name){
return users.get(name);
}
/**
* 通过socket对象找到对应的名称
*/
public String nameBySocket(Socket socket){
for(String key:users.keySet()){
//取出这个key对应的socket
if(socket==users.get(key)){
return key;
}
}
return null;
}
/**
* 获取所有人的socket对象
*/
public synchronized Collection allUsers(){
return users.values();
}
}
- 3.Server类
- 主线程管理监听客户端的连接
//用于保存每一个用户对应的姓名和Socket
public static UserMannager mannager = new UserMannager();
public static void main(String[] args) {
try(ServerSocket ss = new ServerSocket(100)) {
//监听所有来连接的客户端
while(true){
Socket socket = ss.accept();
//让子线程处理一下socket
new ServerThread(socket).start();
}
} catch (IOException e) {
}
}
- ⼦线程处理每个客户端的输⼊输出,判断登录,私聊还是
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
PrintStream ps = null;
try {
//得到对应的输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//得到对应的输出流
ps = new PrintStream(socket.getOutputStream());
String line = null;
while((line=br.readLine())!=null){
//登陆 u+...u+
if(line.startsWith(Chat.LOGIN_FLAG)&&line.endsWith(Chat.LOGIN_FLAG)){
String name = line.substring(2,line.length()-2);
//判断这个用户是否已经登陆
if (Server.mannager.isLogined(name)){
//登录过了
//发送结果给客户端
ps.print(Chat.FAILURE);
}else{
//没有登录
//保存当前登录的用户信息
Server.mannager.save(name,socket);
ps.print(Chat.SUCCESS);
}
}
} catch (IOException e) {
e.printStackTrace();
}
super.run();
}
- 3.Clientr类
- 主线程:接收终端的输入和服务器的输入,并将从终端获取的数据给服务器
public static void main(String[] args) {
BufferedReader br = null;
PrintStream ps = null;
BufferedReader brServer = null;
//连接服务器
try(Socket socket = new Socket("10.129.3.135",100)){
//登录
//接受终端输入流
br = new BufferedReader(new InputStreamReader(System.in));
//发给服务器端的输出流
ps = new PrintStream(socket.getOutputStream());
//接收服务器端的输入流
brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
//接收终端输入信息
String line = JOptionPane.showInputDialog("请输入用户名");
//拼接登陆格式
String loginStr = Chat.LOGIN_FLAG + line + Chat.LOGIN_FLAG;
//发送给服务器端
ps.println(loginStr);
//接收服务器端返回的结果
String result = brServer.readLine();
if (result.equals(Chat.SUCCESS)){
System.out.println("登陆成功");
break;
}else {
System.out.println("用户名已经存在 请重新登录");
}
}
//登陆成功
//开启线程处理服务器的输入
new ClientThread(socket).start();
//接收终端输入 发送给服务器端
String line;
while ((line=br.readLine())!=null){
//发送给服务器
ps.println(line);
}
} catch (IOException e) {
}
}
}
- 子线程:
class ClientThread extends Thread{
private Socket socket;
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br= new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line=br.readLine())!=null){
//发送给服务器
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错!");
}finally {
try {
if (br != null) {
br.close();
}
if (socket != null) {
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
(二)私聊
判断是否为私聊
else if (line.startsWith(Chat.PRIVATE_FLAG)&&line.endsWith(Chat.PRIVATE_FLAG)){
//p+jack♥hellop+
//获取信息
String msg = line.substring(2,line.length()-2);
//分割
String[] items = msg.split(Chat.SPLIT_FLAG);
//用户名
String name = items[0];
//聊天内容
String message = items[1];
//通过用户名找到对应的socket
Socket desSocket = Server.mannager.socketByname(name);
PrintStream desPs = new PrintStream(desSocket.getOutputStream());
//获取当前用户的名称
String currentName = Server.mannager.nameBySocket(socket);
//发送私聊消息
desPs.println(currentName+"向你发来私聊"+message);
(三)群聊
//剩下的一种便是群聊
处理数据
String msg = line.substring(2,line.length()-2);
//获取当前用户的名称
String currentName = Server.mannager.nameBySocket(socket);
//遍历所有的用户信息
Collection sockets = Server.mannager.allUsers();
for (Socket s:sockets) {
PrintStream tempps = new PrintStream(s.getOutputStream());
tempps.println(currentName+"发来群聊"+msg);
(四)今日小结:
今日做的这个实战有着成功也有着失败,成功的是通过这两天重复这些知识点,我逐渐能够知道实现某个功能需要使用什么办法,能跟上写代码的节奏了。失败的地方是我写了之后发现自己什么东西都显示不出来,自己对照了几次,晚上又写了几遍发现还是不想,始终没有找到问题到底出现在哪里,心里很难受啊